使用批处理文件为文件名添加前缀



我可以使用以下命令为一系列文本文件添加前缀:

:: rename files
for %%a in (*.txt) do (
ren "%%a" "Seekret file %%a"
:: ECHO %%a Seekret file %%a
)

哪个会转

a.txt
b.txt
c.txt

Seekret file a.txt
Seekret file b.txt
Seekret file c.txt

但是,上面的代码似乎使用前缀重命名了第一个文件两次。我最终得到

Seekret file Seekret file a.txt

我不知道为什么。有什么想法吗?

使用

for /f "delims=" %%a in ('dir /b /a-d *.txt') do (

正在发生的事情是您正在使用的版本将重命名的文件视为新文件。dir版本构建文件名列表,然后在每行上执行for,因此列表已经构建且是静态的,cmd不会尝试对移动目标进行操作。

另外 - 使用rem,而不是在代码块(括号中的指令序列)中::,因为这种形式的注释实际上是一个损坏的标签,并且标签不允许在code block

是的,这可能会发生,尤其是在 FAT32 和 exFAT 驱动器上,因为这些文件系统不会返回与通配符模式匹配的目录条目列表,以按字母顺序调用可执行文件。for处理一个接一个匹配*.txt目录条目,命令ren导致更改目录条目,即在迭代文件名列表时对其进行修改。

解决方案是使用:

for /F "eol=| delims=" %%I in ('dir *.txt /A-D /B 2^>nul') do ren "%%I" "Seekret file %%I"

在这种情况下,FOR在后台%ComSpec% /c运行,在'之间指定的命令行,这意味着将 Windows 安装到目录 C:\Windows 中:

C:WindowsSystem32cmd.exe /C dir *.txt /A-D /B 2>nul

因此,在后台启动了另一个命令进程,该进程执行DIR

  • 在当前目录中搜索
  • 仅用于文件,因为选项/A-D(属性不是目录)
  • 包括设置了隐藏属性的文件(使用/A-D-H排除隐藏文件)
  • 匹配通配符模式*.txt
  • 并以裸格式输出,由于选项/B.

DIR输出的用于处理STDERR的错误消息(如果未找到任何符合这些条件的目录条目)将通过将其重定向到设备NUL来抑制。

阅读有关使用命令重定向运算符的Microsoft文章,了解2>nul的说明。当 Windows 命令解释器在执行命令 FOR 之前处理此命令行时,重定向运算符>必须在FOR命令行上使用插入符号^进行转义,以使用在后台启动的单独命令进程执行嵌入dir命令行。

没有路径的文件名由DIR输出,以处理后台命令进程的STDOUT。此输出分别由执行批处理文件的命令进程FOR捕获。

启动的命令进程自身终止后,FOR处理捕获的文件名列表。因此,在循环迭代期间对目录所做的所有更改都不再重要。文件名列表不再更改。

需要选项eol=| delims=来获取一个接一个的完整文件名,以循环变量I,即使以;开头或包含空格字符也是如此。eol=|将默认的行尾字符;重新定义为任何文件名都不能包含的垂直条。delims=定义一个空的分隔符列表,以禁用普通空格和水平制表符上的默认换行行为。

注意:::是无效标签,不是注释。不允许在命令块中使用标签,这通常会导致命令块执行时出现未定义的行为。使用命令REM(备注)进行注释。

更好的是:

for /F "eol=| delims=" %%I in ('dir *.txt /A-D /B 2^>nul ^| %SystemRoot%System32findstr.exe /B /I /L /V /C:"Seekret file "') do ren "%%I" "Seekret file %%I"

FINDSTR在这里用于从DIR输出的文件名列表中输出,并重定向到FINDSTRSTDIN所有文件名

  • 不要因为/V(倒置结果)
  • 开始是因为选项/B
  • 由于选项/I区分大小写
  • 由于选项/L字面解释(冗余到/C:)
  • 字符串Seekret file .

需要选项/C:来指定包含两个空格的搜索字符串,因为仅使用"Seekret file"会导致在行首对SeekretORfile进行字面搜索和不区分大小写。在仅用"..."指定的搜索字符串中,每个空格都被FINDSTR解释为 OR 表达式,就像 Perl 正则表达式字符串中的|一样。

使用/C:指定的搜索字符串被隐式解释为文字字符串,但通过使用/R(而不是/L),可以将此字符串解释为正则表达式字符串,其中空格被解释为空格而不是 OR 表达式。可以使用多次/C:指定多个搜索字符串。

我对使用FINDSTR的建议:始终使用/L/R来明确FINDSTR和命令行的每个读者应该如何解释"..."/C:"..."指定的搜索字符串。

我想我也会扔进去,因为我真的不喜欢循环遍历dir输出,而且目前没有其他人在考虑这个脚本已经运行:

@echo off
set "dir=C:YourRootDirectory"
set "pfx=Seekret file "
setlocal enabledelayedexpansion
for /r "%dir%" %%A in (*.txt) do (
set "txt=%%~nA"
if not "!txt:~0,13!"=="%pfx%" ren "%%A" "%pfx%%%~nxA"
)
pause

for /r将递归循环遍历所有.txt文件,将每个文件设置为参数%%A(每次迭代),将变量txt设置为参数%%A减少到仅其名称(%%~nA),然后将文本文件的前 13 个字符与示例前缀进行比较(包含空格时长度为 13 个字符):Seekret file) - 如果它们匹配,则循环不执行任何操作;如果它们不匹配,循环将重命名%%A以在开头包含前缀。如果不希望它是递归的,可以改用for %%A in ("%dir%"*.txt) do (。除此之外,您只需根据前缀是什么或要检查的文件名中有多少个字母来更改!txt:~0,13!。您也不必设置目录和前缀变量,我更喜欢这样做,因为它使块看起来更干净 - 并且更容易返回并更改一个值,而不是该值出现在脚本中的每个位置。

参考:对于/r、ren、变量子字符串

最新更新