批处理脚本 - 重命名文件,删除变量前缀和后缀

时间:2016-02-24 20:16:50

标签: batch-file

我在一个名为

的文件夹中有几个文件
"prefix (S-N 12RE3123) suffix.pdf"

我想将它们重命名为"12RE3123.pdf",删除前缀和后缀。问题是前缀和后缀都有不同的长度/字符,所以我不能只删除第一个/最后一个xx字符重命名,但必须使用唯一的共性,其中只有"S-N"后括号内的字符是那些要保留的。

有一种特殊情况,其中一些序列号被命名为WD-12RE3123,我也需要删除WD-。如果我不得不手动完成,那么它们并不是很多,所以它不会是世界末日,但让它自动化会很好。我想在删除前缀/后缀之后可能会执行if语句来检查前3个字符是否匹配WD-然后删除那些如果为true,但我不确定实现。

我仍然是批处理或vbscript的新手,所以我想知道是否可以在其中任何一个中完成。 Batch有方法“REN”来重命名文件,但由于最终名称取决于当前名称是什么,我不知道如何设置分隔符或如何处理它。

非常感谢任何协助。

3 个答案:

答案 0 :(得分:1)

InlineFrequencyCount

您需要更改@ECHO Off SETLOCAL SET "sourcedir=U:\sourcedir" FOR /f "delims=" %%a IN ( 'dir /b /a-d "%sourcedir%\*(*)*.*" ' ) DO ( FOR /f "tokens=1,2delims=()" %%c IN ("%%a") DO ( FOR /f "tokens=1-3delims=- " %%m IN ("%%d") DO ( IF "%%o"=="" (ECHO(REN "%sourcedir%\%%a" "%%n%%~xa" ) ELSE ( ECHO(REN "%sourcedir%\%%a" "%%o%%~xa" ) ) ) ) GOTO :EOF 的设置以适合您的具体情况。

为了测试目的,所需的REN命令仅为sourcedir在您确认命令正确后,将ECHO更改为ECHO(REN以实际重命名文件。

应用与掩码匹配的每个文件名" "到REN

使用%%a(作为分隔符的令牌,以便括号内的部分位于) 使用%%d-作为分隔符重新标记,以使模式为%%oS-N模式为%%n

显示重命名行。

注意:如果WD-部分不包含括号,并且带括号的部分与描述完全相同,则此方法应该有效。

答案 1 :(得分:1)

以下是针对您的请求的简单解决方案。它依赖于以下事实:

  • prefix部分本身不包含任何括号()suffix可能);
  • 序列号本身不包含任何括号();
  • 没有重复的序列号,也有关于删除潜在的WD-字符串;

这是代码(在目标文件夹中的文件上测试代码之后,您需要删除大写的ECHO命令以实际重命名文件):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Set constants here:
set "LOCATION=.\test"
set "PATTERN=*.pdf"
set STRINGS="S-N " "WD-"

cd /D "%LOCATION%"
for /F "eol=| delims=" %%K in ('dir /B "%PATTERN%"') do (
    for /F "eol=| tokens=2 delims=()" %%L in ("%%~nK") do (
        set "NAME=%%L"
        setlocal EnableDelayedExpansion
        for %%J in (%STRINGS%) do (
            if "!NAME!"=="%%~J!NAME:*%%~J=!" (
                set "NAME=!NAME:*%%~J=!"
            )
        )
        ECHO ren "%%~fK" "!NAME!%%~xK"
        endlocal
    )
)

endlocal
exit /B

工作原理:

  • 第一部分指定文件夹位置,文件模式和要删除的字符串(在()中提取部分之后);根据您的需求调整价值观;
  • 有几个嵌套的for循环;最外面的一个简单地迭代匹配给定模式的所有文件(它基本上读取并解析应用于给定文件的dir命令的输出并循环返回的项;与标准for循环相反,这个for /F方法确保在循环开始迭代之前读取整个文件夹,这在修改枚举文件夹内容时是必要的,就像我们通过重命名文件一样;参见this thread关于该问题的内容);
    • 下一个for /F循环提取感兴趣的文件名部分,即第一对括号之间的所有内容,并将其存储在变量NAME中;这个循环只对每个文件迭代一次;
      • 是另一个for循环,遍历STRINGS变量中的所有项目;
        • if子句检查当前STRINGS项是否出现在NAME值的最开头;如果是的话,它会被删除,否则不会被删除;这只是一个安全查询,因为序列号可能还包含中间或末尾的给定STRINGS项目(例如,123-WD-45A);
      • 此时,重命名已执行(当然已删除ECHO之后);
      • delayed expansion的切换旨在避免文件名中某些特殊字符出现问题;

这是另一个脚本,它使用更复杂的方法来提取文件名的有趣部分。它依赖于以下事实:

  • 文件名中只出现一个子字符串(S-N SPACE
  • 序列号后跟);
  • 序列号本身不包含任何括号();
  • 没有重复的序列号,也有关于删除潜在的WD-字符串;

代码如下所示:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Set constants here:
set "LOCATION=.\test"
set "PATTERN=*.pdf"
set "FILTER=(S-N [^()][^()]*)"
set "IDENTIFYER=S-N "
set STRINGS="WD-"

cd /D "%LOCATION%"
for /F "eol=| delims=" %%K in ('
    dir /B "%PATTERN%" ^| findstr /I /R /C:"%FILTER%"
') do (
    set "NAME=%%K"
    setlocal EnableDelayedExpansion
    set "NAME=!NAME:*(%IDENTIFYER%=!"
    for /F "eol=| tokens=1 delims=)" %%L in ("!NAME!") do (
        setlocal DisableDelayedExpansion
        set "NAME=%%L"
        setlocal EnableDelayedExpansion
        for %%J in (%STRINGS%) do (
            if "!NAME!"=="%%~J!NAME:*%%~J=!" (
                set "NAME=!NAME:*%%~J=!"
            )
        )
        ECHO ren "%%~fK" "!NAME!%%~xK"
        endlocal
        endlocal
    )
    endlocal
)

endlocal
exit /B

基本上,这个脚本与上面的脚本类似,只有一些偏差:

  • 第一部分另外指定文件名过滤器和序列号标识符(S-N);
  • 最外层dir循环中的for命令通过管道传输到findstr命令,以过滤掉不包含(S-N)的文件以及字符串(在开头已经不包含( / ));
    • 部分(S-N以及之前的所有内容都已删除,结果存储在NAME;
    • 下一个for /F循环从)值中提取所有内容但不包括第一个NAME,这构成了感兴趣的文件名部分;这个循环只对每个文件迭代一次;
      • 是另一个for循环,遍历STRINGS变量中的所有项目,此变量在此处不包含S-N部分,因为之前已将其删除;此循环中的其余部分与上述脚本中的相同;
      • 此时,重命名已执行(当然已删除ECHO之后);

答案 2 :(得分:1)

Magoo和aschipfl都提供了良好的纯批次解决方案。

我发现为每个复杂的重命名任务开发自定义批处理脚本都很乏味,这就是我编写JREN.BAT - a regex find/replace renaming utility的原因。 JREN.BAT是纯脚本(混合JScript /批处理),可以在XP以后的任何Windows机器上本机运行。可以通过jren /?从命令行获取完整文档,也可以使用jren /??获取分页帮助。

使用JREN.BAT,解决方案就像(未经测试)一样简单:

jren "^.*\((?:S-N (?:WD-)?)(.+?)\).*" "$1.jpg" /fm *.jpg

如果我的正则表达式错误,可以轻松修复。您应该首先添加/T选项以在测试模式下运行命令,然后在一切看起来都很好时将其删除。

如果将命令放在批处理脚本中,则必须使用CALL JREN。