-1

我在这里。我正在尝试编写一个 .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%

我尝试使用的方法是获取每一行并删除符号之前(包括\符号)的所有内容。到目前为止,我已经能够让脚本在没有错误的情况下结束,但它实际上并没有做任何事情。

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

4

1 回答 1

0
@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.... )到一个新文件中。(>>代替>将附加到现有文件,或者如果没有现有文件则创建一个新文件......)使用name 和 eX张力命名%%G。如果您想要.txt输出文件而不是.M3u(匹配 中的扩展名%%G),那么您只需使用%%~nG.txt.

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

文件名也是如此%%q。将for/f其用作文字(由"quoting"它)处理,然后我们可以使用它%%~nxs来“显示” 的“名称和扩展名” %%s

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

好吧,tokens=*基本上delims=做同样的事情(但前者抑制了像空格这样的前导分隔符)。eol=~会截断dir之前的任何文件名输出~,这可能实际上没有发生 - 这只是一个潜伏的问题。

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

其次,更严重的是,当您Remove在下一行中使用时,将使用遇到Remove时的值,for因为您的代码使用%Remove...%. 要按预期使用当前值,您需要打开delayedexpansion(如您所愿)并使用!Remove...!. 即使在那里,您也会尝试将处理后的值分配给result.

使用set "remove=%%G"会更好一些(不是你想要的,文件%%G名也是.m3u如此 - 不是它的内容,但更好)然后你会尝试设置resultthe 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:\.

然后 - echoing%result%将不会echo编辑任何内容,因为在遇到result时没有任何价值forecho !result!可能工作得更好一些(!因为值已被循环修改)but thenecho with an argument that is resolved to *nothing* reportsecho is off`(或打开,视情况而定),而不是预期的空行。

复杂,是吗?没关系 - 一旦你掌握了它的窍门,批处理就会很有趣。

于 2020-10-11T20:35:56.873 回答