Batch file 搜索特定扩展名的文件名并删除特殊字符

Batch file 搜索特定扩展名的文件名并删除特殊字符,batch-file,for-loop,rename,batch-rename,Batch File,For Loop,Rename,Batch Rename,我正在尝试编写一个修补程序文件,该文件将执行以下操作: 搜索w:\以查找所有*.pdf和*.xls文件。有许多目录和子目录要搜索 我需要搜索文件名并替换以下内容。并非每个文件名中都包含这些不需要的字符。 查找并替换为和(&D) 找到#并移除# 找到“有限公司”(在“L”前面有一个空格)并将其删除 如果进行了上述任何更改,请重命名该文件 输出所有已更改文件的文件 我有一些问题,因此我在这里的职位。我已经能够从这个网站上的其他帖子中拼凑出这段代码。这就是我目前所拥有的。对我放松点,我在大学里

我正在尝试编写一个修补程序文件,该文件将执行以下操作:

  • 搜索w:\以查找所有*.pdf和*.xls文件。有许多目录和子目录要搜索
  • 我需要搜索文件名并替换以下内容。并非每个文件名中都包含这些不需要的字符。
    • 查找并替换为和(&D)
    • 找到#并移除#
    • 找到“有限公司”(在“L”前面有一个空格)并将其删除
  • 如果进行了上述任何更改,请重命名该文件
  • 输出所有已更改文件的文件
我有一些问题,因此我在这里的职位。我已经能够从这个网站上的其他帖子中拼凑出这段代码。这就是我目前所拥有的。对我放松点,我在大学里已经18年没有做过任何编程了

我正在使用一个名为Take Command by JP Software的程序,这样我就可以使用某种调试器,试图找出我做错了什么

谢谢你的帮助

@Echo OFF
set /A xcount=0
set root=c:\clients
Set logfilename=Changed.txt
cd %root%

for /f "delims=" %%a in ('dir /a:-d /o:n /b /s *.pdf *.xls') do call :next "%%a"
echo. >> %root%\%logfilename%
echo End of file > %root%\%logfilename%
pause
GOTO:EOF

:next
    set "current=%~nx1"
    set "newname=%~nx1"
    set "newname=%newname:&=and%"
    set "newname=%newname:#=%"
    set "newname=%newname: LTD.=%"
    set "newname=%newname:%=%"
    set "newname=%newname::=%"

If "%current%" == "%newname%" goto nope
    SET /A xcount+=1
    ren "%current%" "%newname%"
    echo "%current%" "%newname%"
    echo %xcount% - "%current%" "%newname%" > %root%\%logfilename%
:nope

我看到两个主要问题:

1) REN命令必须具有源文件的完整路径。您仅提供名称和扩展名

2) 看起来您也在尝试删除
%
字符。正常扩展无法完成此操作-需要延迟扩展。另外,
%
必须加倍

我发现了一些效率低下的问题:

1) 不需要任何电话或转到。两者都相对缓慢。使用括号可以在一个循环内完成所有操作。如果有许多文件要处理,性能差异可能会很大。请注意,使用已在块内设置的变量需要延迟扩展

2) 重复打开和关闭日志文件以附加更多信息的速度很慢。将整个块括在括号内并只重定向一次更有效

3) 您正试图从名称中删除
。这不是必需的,因为Windows文件名不能包含

4) 您已经将当前目录设置为根目录,因此重定向时不需要包含路径

以下是我未经测试的解决方案的几点注意事项:

1) 延迟扩展在循环中打开和关闭,以保护任何
。如果变量包含
,则在扩展时会损坏和延迟扩展已启用

2) 我使用了
echo(
而不是
echo.
来回送一个空行。这种语法看起来很奇怪,但总是有效的。
echo.
synyax在某些模糊的条件下可能会失败

3) 我使用PUSHD insead of CD将当前目录设置为您的根目录。如果您正在更改当前卷(例如从D:更改为C:),则如果没有/D选项,CD将无法正常工作

4) 外部块将非标准/未使用的文件句柄重定向到日志文件。然后在块内,特定的输出被重定向到日志文件句柄。这样做是为了使日志文件不必重复打开、重新定位到末尾和关闭。其他输出转到正常标准输出

@echo off
setlocal disableDelayedExpansion
set /a xcount=0
set "root=c:\clients"
Set "logfile=Changed.txt"
pushd "%root%"

3>"%logfile%" (
  for /f "delims=" %%F in ('dir /a:-d /o:n /b /s *.pdf *.xls') do (
    set "file=%%~fF"
    set "old=%%~nxF"
    set "new=%%~nxF"
    setlocal enableDelayedExpansion
    set "new=!new:&=and!"
    set "new=!new:#=!"
    set "new=!new: LTD.=!"
    set "new=!new:%%=!"
    if "!new!" neq "!old!" (
      set /a xcount+=1
      ren "!file!" "!new!"
      echo "!file!" "!new!"
      echo !xcount! - "!file!" "!new!">&3
    )
    endlocal
  )
  echo(>&3
  echo End of file>&3
)
popd
pause
exit /b
注意-上述解决方案实现了您所述的规则。但有一个问题。像
“Acme LTD.pdf”
这样的名称将被重命名为
“Acmepdf”


更新

自从回答这个问题以来,我已经编写了一个名为的方便实用程序,它可以非常简单地解决这个问题。该实用工具通过对文件名执行正则表达式搜索和替换来执行重命名操作。是一个混合JScript/批处理脚本,从XP开始在任何Windows计算机上本机运行

<>我已经修改了您的规则,以便在扩展之前立即保存<代码>有限公司>代码>,并且在名称中间出现<代码>有限公司>代码>删除点。

假设当前目录中有JREN.BAT,或者更好,路径中的某个地方有JREN.BAT,那么下面的脚本应该可以实现这一点

renFiles.bat

@echo off
call jren "(&)|(#|%| LTD(?=\.[^.]*$)| LTD\.)" "$1?'and':''" /i /s /j /fm "*.pdf|*.xls" %1 >rename.log
type rename.log
我建议使用
/T
选项在测试模式下运行上述操作。它只列出建议的重命名操作,而不实际重命名任何内容

renFiles /T

验证一切正常后,然后在没有给定目录的情况下再次运行
/T

u:\sourcedir\T w o

 Volume in drive U has no label.
 Volume Serial Number is 0460-0000

 Directory of u:\sourcedir\t w o

14/12/2014  00:05    <DIR>          .
14/12/2014  00:05    <DIR>          ..
14/12/2014  00:28                 0 dum myfile2.txt
14/12/2014  00:28                 0 file1.xls
14/12/2014  00:28                 0 file2.xls
14/12/2014  00:28                 0 file3.xls
14/12/2014  00:28                 0 amper&1.pdf
14/12/2014  00:28                 0 amper&2.pdf
14/12/2014  00:28                 0 amper&3.pdf
14/12/2014  00:28                 0 hash#1.xls
14/12/2014  00:28                 0 hash#2.xls
14/12/2014  00:28                 0 hash#3.xls
14/12/2014  00:28                 0 LTD LTD 1.pdf
14/12/2014  00:28                 0 LTD LTD 2.pdf
14/12/2014  00:28                 0 LTD LTD 3.pdf
14/12/2014  00:28                 0 lower ltd 1.pdf
14/12/2014  00:28                 0 lower ltd 2.pdf
14/12/2014  00:28                 0 lower ltd 3.pdf
14/12/2014  00:28                 0 ALL#& LTD 1.pdf
14/12/2014  00:28                 0 ALL#& LTD 2.pdf
14/12/2014  00:28                 0 ALL#& LTD 3.pdf
14/12/2014  00:28                 0 shriek!hello!1.pdf
14/12/2014  00:28                 0 shriek!hello!2.pdf
14/12/2014  00:28                 0 shriek!hello!3.pdf
14/12/2014  00:28                 0 pcnt%hello%1.pdf
14/12/2014  00:28                 0 pcnt%hello%2.pdf
14/12/2014  00:28                 0 pcnt%hello%3.pdf
14/12/2014  00:28                 0 co,mm,a1.pdf
14/12/2014  00:28                 0 co,mm,a2.pdf
14/12/2014  00:28                 0 co,mm,a3.pdf
14/12/2014  00:28                 0 se;mi1.pdf
14/12/2014  00:28                 0 se;mi2.pdf
14/12/2014  00:28                 0 se;mi3.pdf
14/12/2014  00:28             1,074 newfile.txt
              32 File(s)          1,074 bytes
               2 Dir(s)   2,099,904,512 bytes free
u:\sourcedir\t w o\newfile.txt中生成

REN "amper&1.pdf" "amperand1.pdf"
REN "amper&2.pdf" "amperand2.pdf"
REN "amper&3.pdf" "amperand3.pdf"
REN "LTD LTD 1.pdf" "LTD 1.pdf"
REN "LTD LTD 2.pdf" "LTD 2.pdf"
REN "LTD LTD 3.pdf" "LTD 3.pdf"
REN "lower ltd 1.pdf" "lower 1.pdf"
REN "lower ltd 2.pdf" "lower 2.pdf"
REN "lower ltd 3.pdf" "lower 3.pdf"
REN "ALL#& LTD 1.pdf" "ALLand 1.pdf"
REN "ALL#& LTD 2.pdf" "ALLand 2.pdf"
REN "ALL#& LTD 3.pdf" "ALLand 3.pdf"
REN "shriek!hello!1.pdf" "shriek!hello!1.pdf"
REN "shriek!hello!2.pdf" "shriek!hello!2.pdf"
REN "shriek!hello!3.pdf" "shriek!hello!3.pdf"
REN "pcnt%hello%1.pdf" "pcnt%hello%1.pdf"
REN "pcnt%hello%2.pdf" "pcnt%hello%2.pdf"
REN "pcnt%hello%3.pdf" "pcnt%hello%3.pdf"
REN "co,mm,a1.pdf" "co,mm,a1.pdf"
REN "co,mm,a2.pdf" "co,mm,a2.pdf"
REN "co,mm,a3.pdf" "co,mm,a3.pdf"
REN "se;mi1.pdf" "se;mi1.pdf"
REN "se;mi2.pdf" "se;mi2.pdf"
REN "se;mi3.pdf" "se;mi3.pdf"
REN "file1.xls" "file1.xls"
REN "file2.xls" "file2.xls"
REN "file3.xls" "file3.xls"
REN "hash#1.xls" "hash1.xls"
REN "hash#2.xls" "hash2.xls"
REN "hash#3.xls" "hash3.xls"

相比之下,批处理文件很难读、写、调试,而且功能也不是很强大。也许你用另一种语言做这件事会更容易,也许C#或VisualBasic根本不反对你。回到大学后我很擅长C++,但那是很久以前的事了。我怀疑我今天能在C++中做一个“你好世界”的节目。几年前,我也做了一点visual basic。我是一个网络人,不是一个程序员。所以我真的需要一些东西来编写像这样快速的小程序。这个小的批处理文件在工作时将节省员工一天的工作时间。除了dbenhams之外,只需做一点注释回答:如果您想调用一个子例程,您必须使用
goto:eof
结束此例程以返回。@speising-或EXIT/B,或者如果例程位于文件末尾,则两者都不返回。但是最好总是有EXIT/B或GOTO:EOF,以防以后添加另一个例程。为什么需要文件变量ren“%%F”不够?如果它包含
,则@unrelated-
%%F
将被损坏因为已启用延迟扩展。在启用延迟扩展之前,必须设置文件的值。谢谢dbenham。我必须同意上面的一条评论,-相比之下,批处理文件很难读,很难写,很难调试。当我试图理解你的代码时,我复制并粘贴到我正在使用的调试器中