批处理文件可删除绝对路径,并在多个文件中仅保留文件名

问题描述

在这里头晕。我正在尝试编写一个.bat文件,该文件将遍历多个.m3u播放列表文件中的每一行,以删除路径并仅保留文件名。

示例输入:

    C:\Users\username\Music\Dr. Dre\Dr. Dre & Snoop Doggy Dog - Ain't Nothin But A G-Thang.mp3
    C:\Users\username\Music\Ed Sheeran\x (Deluxe Edition)\04 Don't.mp3
    C:\Users\username\Music\Eric Church\Chief (2011)\06-eric_church-homeboy.mp3

所需的输出

    Dr. Dre & Snoop Doggy Dog - Ain't Nothin But A G-Thang.mp3
    x (Deluxe Edition)\04 Don't.mp3
    06-eric_church-homeboy.mp3

搜索过高和低,没有运气获得期望的输出。我也没有足够的经验来简化此过程。在我多次失败的尝试中,到目前为止,这是我想到的:

    @echo off
    setlocal enableDelayedExpansion
    for /f "tokens=* delims= eol=~" %%G in ('dir /b "C:\Users\username\Documents\Playlists\*.m3u"') do (
    SET Remove=*
    SET Result=%remove:*\=% )
    ECHO %result%

我尝试使用的方法删除每一行并删除\符号之前(包括该符号)的所有内容。到目前为止,我已经能够顺利完成脚本的运行,但是实际上并没有做任何事情。

任何帮助将不胜感激。预先谢谢你。

解决方法

@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"

for /f "delims=" %%G in ('dir /b /a-d "%sourcedir%\*.m3u"') do (
 REM "%%G" contains the name+extension of each M3U file in turn
 for /F "usebackq delims=" %%q in ("%sourcedir%\%%G") do (
  rem %%q contains the entire contents of the file "%%G" - each such line is itself a full-filename
  for /f "delims=" %%s in ("%%q") do echo %%~nxs
 )
)>"%destdir%\%%~nxG"

GOTO :EOF

您需要根据自己的情况更改sourcedirdestdir的设置。清单使用适合我系统的设置。

在第一行中,将dir/b输出分配给元变量 %%G。如果遇到适合/a-d的目录名,则*.m3u开关将关闭目录名。

"delims="dir输出的行分配给%%G-整行,仅此行。这些行是扫描目录时遇到的文件的名称。

请注意结构for ... do ( ....whatever.... )>"filename"。这意味着将( ....whatever.... )的所有输出收集到一个新文件中。 (>>代替>会附加到现有文件,如果没有现有文件,则创建一个新文件...)使用n和e {{1 }} X的张力。如果您希望使用%%G而不是.txt(匹配.M3u中的扩展名)的输出文件,则只需使用%%G

现在,我们处理每个文件“ %%~nG.txt”。由于名称​​可能包含空格,因此需要使用%%G选项。同样,usebackq将从文件读取的整个行分配给delims=

因此%%q是文件名。使用%%q作为文字(通过for/f处理),然后我们可以使用"quoting"“显示” %%~nxs的“名称和扩展名”。

那么-您的版本出了什么问题?

好吧,%%stokens=*本质上是做相同的事情(但是前者禁止使用前导定界符,例如空格)。 delims=会在eol=~之前截断dir的任何来自~的文件名输出,这实际上可能没有发生-这只是一个潜伏的问题。

在循环中,您正在设置remove。这里有两个小问题。首先,最好使用语法SET "var=value"(其中值可能为空;在这种情况下var变为 undefined )可确保不将任何结尾的空格分配的值。

第二,更重要的是,当您在下一行中使用Remove时,将使用遇到Remove时的for值,因为您的代码使用了{ {1}}。要按预期使用 current 值,需要打开%Remove...%(如您所愿)并使用delayedexpansion。即使在那儿,您也尝试将处理后的值分配给!Remove...!

使用result会更好一些(不是您想要的,因为set "remove=%%G"%%G文件的名称-不是内容,而是更好),然后您d尝试将.m3u设置为result

因此,如果您要像预期的那样处理变量的内容例如是the contents of "remove" with all leading characters up to and including the first "\" replaced by *nothing*,那么结果将仅仅是删除C:\Users\username\Music\Ed Sheeran\x (Deluxe Edition)\04 Don't.mp3

然后-C:\echo都没有{em> ,因为%result%echo出现时没有任何价值。遇到。 result的效果可能更好一些(for,因为该值已被循环修改)echo !result! echo ! echo关闭(或视情况打开)是),而不是预期的空行。

复杂吗?没关系-一旦掌握了批处理功能就很有趣。