【问题标题】:Batch .BAT script to rename files批处理 .BAT 脚本重命名文件
【发布时间】:2014-12-01 15:53:30
【问题描述】:

我正在寻找一个批处理脚本来(递归地)重命名一个文件夹。 重命名示例: 34354563.randomname_newname.png 到 newname.png

我已经挖掘了 RegEx 以匹配从字符串开头到第一个下划线(其 ^(.*?)_ ),但无法说服 Windows Batch 让我使用 RegEx 进行复制或重命名。

【问题讨论】:

    标签: regex windows batch-file


    【解决方案1】:

    从命令行提示符 - 没有 :

    FOR /R %f IN (*.*) DO FOR /F "DELIMS=_ TOKENS=1,*" %m IN ("%~nxf") DO @IF NOT "%n" == "" REN "%f" "%n"
    

    在批处理文件中,双 %:

    FOR /R %%f IN (*.*) DO FOR /F "DELIMS=_ TOKENS=1,*" %%m IN ("%%~nxf") DO @IF NOT "%%n" == "" REN "%%f" "%%n"
    

    编辑:一个新的纯批处理解决方案发出以下案例:

    • Path\File_name.ext => name.ext
    • Path\none.ext(什么都不做)
    • 路径\Some_file_name.ext => 文件名.ext
    • Path\name.some_ext(什么都不做)
    • Path\Some_file_name.some_ext => name.some_ext

    批处理(移除 ECHO 以使其正常运行):

    FOR /R %%f IN (*.*) DO CALL :UseLast "%%~f" "%%~nf"
    
    GOTO :EOF
    
    :UseLast
    FOR /F "DELIMS=_ TOKENS=1,*" %%m IN (%2) DO IF "%%n"=="" (
        IF NOT "%~2"=="%~n1" ECHO REN %1 "%~2%~x1"
    ) ELSE CALL :UseLast %1 "%%n"
    GOTO :EOF
    

    【讨论】:

    • OP 没有声明使用长文件名,但允许它们不会有什么坏处。在上面最后一个代码的末尾使用REN "%%f" "%%n"
    • @foxidrive Ups,错过了!谢谢!
    • 也许这不太可能,但是像test.a_b 这样的名字会变成b
    • 是的,我知道。 @Endoro 提出了这个问题。
    • 嗯 - OP 指定“第一个下划线”,所以我认为需要的是在第一个下划线之前删除部分。或者可能是,规范很不清楚。在任何情况下,我都建议 Kosher 检查建议的目标文件名是否不存在......
    【解决方案2】:

    避免在扩展中使用_

    @ECHO OFF 
    FOR /F "DELIMS=" %%A IN ('DIR /S /B /A-D *_*.*') DO FOR /F "TOKENS=1*DELIMS=_" %%B IN ("%%~NA") DO IF "%%~C" NEQ "" ECHO REN "%%~A" "%%~C%%~XA"
    

    查看输出,如果看起来不错,删除 ECHO

    【讨论】:

    • +1,您的解决方案将保留第一个 _ 之后的名称。 a_b_c_d.txt 之类的名称将变为 b_c_d.txt,这可能会也可能不会。有关其他选择,请参阅我的答案。
    • +1 使用ECHO 轻松预览结果并轻松提交结果的好主意。
    • 我不知道批处理脚本,但只有当我在REN 之前删除ECHO 时,它才能作为.cmd 工作。
    • @DanielCheung 是的,正如我在回答中所说:“查看输出,如果看起来不错,请删除 ECHO。”
    【解决方案3】:

    标准的 windows shell 没有正则表达式功能,实际上它非常基础。但是您可以使用 powershell 来执行此操作。

    我对 power shell 不是很熟悉,但是另一个问题解释了如何过滤文件:Using powershell to find files that match two seperate regular expressions

    【讨论】:

      【解决方案4】:

      新解决方案

      有一个非常简单的解决方案,使用 JREN.BAT,我新的混​​合 JScript/batch 命令行实用程序,用于通过正则表达式搜索和替换重命名文件和文件夹。

      只重命名带有一个下划线的文件:

      jren "^[^_]+_([^_]+\.png)$" "$1" /s /i
      

      保留第一个下划线之后的所有内容:

      jren "^.*?_" "" /s /fm "*.png"
      

      保留最后一个下划线之后的所有内容:

      jren "^.*_" "" /s /fm "*.png"
      


      ============================================= ==============

      原答案

      这可以使用hybrid JScript/batch utility called REPL.BAT 在标准输入上执行正则表达式搜索和替换并将结果写入标准输出来完成。以下所有解决方案都假定 REPL.BAT 位于您的 PATH 中。

      我故意将 ECHO 设置为 ON,以便您获得执行的重命名命令的日志。如果您遇到名称冲突,这一点尤其重要:两个不同的起始名称都可能合并为相同的新名称。只有第一次重命名会成功 - 第二次会失败并显示错误消息。

      我有三种解决方案,它们的区别仅在于它们如何处理包含超过 1 个_ 字符的名称。

      此解决方案只会重命名名称中恰好有一个 _ 的文件(不考虑扩展名)。 a_b_c_d.txt 之类的名称将被忽略。

      @echo on&@for /f "tokens=1,2 delims=*" %%A in (
        '2^>nul dir /b /s /a-d *_* ^| repl ".*\\[^_\\]*_([^_\\]*\.[^.\\]*)$" "$&*$1" a'
      ) do ren "%%A" "%%B"
      

      下一个解决方案将保留最后一个 _ 之后的名称。像a_b_c_d.txt 这样的名字会变成d.txt

      @echo on&@for /f "tokens=1,2 delims=*" %%A in (
        '2^>nul dir /b /s /a-d *_* ^| repl ".*_([^\\_.]*\.[^.\\]*)$" "$&*$1" a'
      ) do echo ren "%%A" "%%B"
      

      最后一个解决方案将保留第一个 _ 之后的名称。像a_b_c_d.txt 这样的名字会变成b_c_d.txt。这应该给出与 Endoro 答案相同的结果。

      @echo on&@for /f "tokens=1,2 delims=*" %%A in (
        '2^>nul dir /b /s /a-d *_* ^| repl ".*\\[^\\]*?_([^\\]*\.[^.\\]*)$" "$&*$1" a'
      ) do echo ren "%%A" "%%B"
      

      【讨论】:

      • 你用这么重的武器来完成这么简单的任务。如果要使用 JScript,一个 JScript 文件就足够了,而不是 2 个 bat 和 1 个 js。如果运行两次或更多次,我的解决方案(和@Endoro 一个)将达到相同的结果。在我看来,即使是批处理内的简单循环也会比这种解决方案更好。
      • @LS_dev - REPL.BAT 是一个方便的实用程序,可以在很多情况下使用。当然,仅仅为此而开发它是没有意义的,但是一旦你拥有它,为什么不使用它呢?是的,您可以使用纯批处理或单个 JScript 或 VBS 来实现所有三个结果。但是一旦你的武器库中有 REPL.BAT,编码就更简单了。如果您想获得我的最后一个结果,您或 Endoro 的解决方案没有任何问题。但是多次运行以获得我的第二个解决方案是不切实际的。您如何知道需要运行多少次?您可以使用正则表达式添加 FINDSTR 以获得我的第一个结果。
      • 我承认你写REPL.BAT的优点。但作为一个方便的实用程序,为了提高效率,我更喜欢sed。 1 exe 优于 1 bat > 1 exe > 1 js 和返回。
      • 是的,不错的 REPL 工具,而且速度也很快。但是您的正则表达式不适用于没有扩展名的文件。我不知道,这是否是一个真正的问题。
      • @Endoro - 是的,仅适用于书面扩展。对正则表达式的轻微更改可以处理没有扩展名的名称:在文字点之后使用?,另外可能需要在其中一个术语之后使用+,以保证_ 之后至少有一个字符。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多