使用批处理编辑文件名



所以我正在编写用于文件重命名/编辑的脚本,但出现错误
The system cannot find the file specified

我假设这是因为循环,我该如何解决这个问题

@echo off
Setlocal enabledelayedexpansion
cd /d "%~dp0"
for /f "delims=*" %%a IN ('dir /b /s /a-d "Folder1(*)*.txt"') DO (
Set "File=%%~nxa"
Ren "%%a" "!File:(1)=(-125)!"
Ren "%%a" "!File:(2)=(-124)!"
Ren "%%a" "!File:(3)=(-121)!"
Ren "%%a" "!File:(4)=(-117)!"
Ren "%%a" "!File:(5)=(-120)!"
Ren "%%a" "!File:(6)=(-116)!"
Ren "%%a" "!File:(7)=(-115)!"
Ren "%%a" "!File:(8)=(-127)!"
Ren "%%a" "!File:(9)=(-126)!"
Ren "%%a" "!File:(10)=(-100)!"
)
Source Folder1
(1) filename.txt
(2) filename.txt
(3) filename.txt
Source Folder1 Results
(-125) filename.txt
(-124) filename.txt
(-121) filename.txt

如您所见,该脚本确实有效,但是我收到消息
,我也用相同的结果
对其进行了测试for /f "Tokens=*"

可以使用以下代码来完成此任务。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0Folder1" || exit /B
for /F "delims=" %%I in ('dir "(*)*.txt" /A-D-L /B 2^>nul') do (
set "FileName=%%I"
setlocal EnableDelayedExpansion
set "NewName=!FileName:(1)=(-125)!"
set "NewName=!NewName:(2)=(-124)!"
set "NewName=!NewName:(3)=(-121)!"
set "NewName=!NewName:(4)=(-117)!"
set "NewName=!NewName:(5)=(-120)!"
set "NewName=!NewName:(6)=(-116)!"
set "NewName=!NewName:(7)=(-115)!"
set "NewName=!NewName:(8)=(-127)!"
set "NewName=!NewName:(9)=(-126)!"
set "NewName=!NewName:(10)=(-100)!"
ren "!FileName!" "!NewName!"
endlocal
)
popd
endlocal

首先定义所需的执行环境

  • 命令回显模式关闭并
  • 已启用命令扩展,并且
  • 延迟变量扩展禁用。

接下来,批处理文件目录的子目录Folder1将成为当前工作目录,或者如果该文件夹根本不存在,则退出批处理文件处理。

然后在后台启动另一个 Windows 命令进程,%ComSpec% /c和命令FOR'中的命令行作为附加参数追加。有在Windows安装到C:Windows中执行:

C:WindowsSystem32cmd.exe /c dir "(*)*.txt" /A-D-L /B 2>nul

命令DIR搜索

  • 在当前目录中
  • 由于/A-D-L(属性不是目录而不是链接(重新解析点)),仅针对文件)
  • 文件名与通配符模式匹配(*)*.txt
  • 由于/B,仅以裸格式输出没有路径的匹配名称。

DIR可能找不到匹配的文件名,在这种情况下,会输出错误消息,通过将其从STDERR(标准错误)重定向到设备NUL来抑制该消息。

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

选项的 FOR/F捕获已启动cmd.exe的所有输出到STDOUT(标准输出),并等待启动cmd.exe的自终止,然后再逐行处理捕获的输出。

忽略此处根本不存在的空行。默认情况下,将使用普通空格和水平制表符作为字符串分隔符将文件名拆分为子字符串,如果第一个子字符串以分号开头,则分析,在这种情况下,行(文件名)也将被忽略,否则第一个空格/制表符分隔的子字符串在运行FOR正文中的命令之前I分配给指定的循环变量。

不需要行(文件名)拆分行为,这就是使用选项delims=来定义字符串分隔符的空列表以关闭将行拆分为子字符串的原因。在这种情况下,可以保留默认的行尾字符;,因为要处理的所有文件名都以字符(开头。

没有路径的文件名首先分配给环境变量FileName该变量也适用于包含一个或多个感叹号的文件名,因为在执行此命令行时禁用延迟变量扩展。

"下一步"根据下一个命令的需要启用延迟变量扩展。请阅读此答案,了解有关命令SETLOCALENDLOCAL的详细信息,以及使用这两个命令运行进程cmd内存中实际发生的情况。

接下来使用命令SET完成一系列字符串替换,以根据当前文件名定义新文件名,然后仅运行一次命令REN将当前文件重命名为新名称。

问题中发布的代码尝试多次重命名文件。它在字符串替换时失败根本不会改变任何东西,因为文件无法在新名称等于当前名称时重命名。然后,一个REN命令工作,字符串替换成功。另一个REN命令再次失败,因为文件已重命名,并且由于该原因,再次使用原始文件名重命名它无法再工作。

禁用延迟变量扩展的初始环境在处理下一个文件名之前最后恢复。

也可以用于此任务:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0Folder1" || exit /B
for %%# in ("1 125" "2 124" "3 121" "4 117" "5 120" "6 116" "7 115" "8 127" "9 126" "10 100") do for /F "tokens=1,2" %%G in (%%#) do for %%I in ("(%%G)*.txt") do for /F "tokens=1* delims=)" %%J in ("%%I") do ren "%%I" "(-%%H)%%K"
popd
endlocal

对于每对当前数字和新数字,将执行字符串拆分以将当前编号分配给循环变量G并将新编号分配给循环变量HFOR用于处理具有当前编号 (G) 的所有文件之前,其中文件名被分配给循环变量I在第一次出现右圆括号时拆分以获得部分首先从整个文件名)后,文件扩展名分配给循环变量K以便能够使用新编号重命名文件。

还有其他几种可能的解决方案。

要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,然后完整而仔细地阅读每个命令的显示帮助页面。

  • call /?......解释%~dp0...参数 0 的驱动器和路径,这是始终以反斜杠结尾的批处理文件路径。
  • dir /?
  • echo /?
  • endlocal /?
  • exit /?
  • for /?
  • popd /?
  • pushd /?
  • ren /?
  • set /?
  • setlocal /?

另请阅读使用 Windows 批处理文件的单行包含多个命令,了解在第三||命令行上使用的条件命令运算符的说明。


第一个批处理文件解决方案,还处理子文件夹中的文件:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0Folder1" || exit /B
for /F "delims=" %%I in ('dir "(*)*.txt" /A-D-L /B /S 2^>nul') do (
set "FullName=%%I"
set "FileName=%%~nI"
setlocal EnableDelayedExpansion
set "NewName=!FileName:(1)=(-125)!"
set "NewName=!NewName:(2)=(-124)!"
set "NewName=!NewName:(3)=(-121)!"
set "NewName=!NewName:(4)=(-117)!"
set "NewName=!NewName:(5)=(-120)!"
set "NewName=!NewName:(6)=(-116)!"
set "NewName=!NewName:(7)=(-115)!"
set "NewName=!NewName:(8)=(-127)!"
set "NewName=!NewName:(9)=(-126)!"
set "NewName=!NewName:(10)=(-100)!"
ren "!FullName!" "!NewName!%%~xI"
endlocal
)
popd
endlocal

第二个批处理文件解决方案,还处理子文件夹中的文件:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0Folder1" || exit /B
for %%# in ("1 125" "2 124" "3 121" "4 117" "5 120" "6 116" "7 115" "8 127" "9 126" "10 100") do for /F "tokens=1,2" %%G in (%%#) do for /R %%I in ("(%%G)*.txt") do for /F "tokens=1* delims=)" %%J in ("%%~nxI") do ren "%%I" "(-%%H)%%K"
popd
endlocal

FOR 循环忽略了具有隐藏属性集的文本文件,在批处理文件目录的子目录Folder1中递归搜索将圆括号中的数字分配给循环变量G的文件。

最新更新