【问题标题】:Replacing only first _ character from filename using Batch使用批处理仅替换文件名中的第一个 _ 字符
【发布时间】:2022-07-30 02:40:17
【问题描述】:

首先,批处理文件应该只能在我复制它的任何文件夹中工作。

例如,我有一个这样的文件名;

TEST2-FILE-REPLACE_05_07

我希望这个文件名改变如下。它只会用“+”替换第一个“_”字符。其他_将保持不变

TEST2-FILE-REPLACE+05_07

谁能告诉我怎么做?下面的代码有效,但使所有“下划线”字符为“+”。我只希望它使第一个“下划线”字符“+”。

@echo off
setlocal enabledelayedexpansion
for %%a in (*_*) do (
  set file=%%a
  ren "!file!" "!file:_=M!"
)

【问题讨论】:

  • 最好的办法是停止使用cmd,开始使用powershell :-) 比如windowscentral.com/…。如果你必须使用cmd,请下载第三方工具,让你的生活更轻松(如prename)。
  • 上面的代码有效但是它改变了所有的下划线我希望它只改变第一个谢谢你提供的方法但是每次我需要改变它时都会有数百个文件这样.如果按照我上面给出的方法一键搞定的话,我会节省很多时间。
  • for /f "tokens=1,* delims=_" %%G in ('dir /a-d /b *_*') do ren "%%G_%%H" "%%G+%%H"
  • @Squashman 非常感谢你!这就是我需要的!
  • @paxdiablo,当您可以在for 循环中简单地使用tokens 时,建议使用第三方工具有点极端?

标签: batch-file batch-rename


【解决方案1】:

您的代码存在以下问题:

  1. Sub-string substitution 语法会替换所有出现的搜索字符串,因此这是错误的方法。但是,使用 for /F loop,您可以在某些分隔符处拆分字符串。
  2. standard for loop 不会提前构建整个文件列表,因此文件可能会被重命名两次。所以先用dir构建整个文件列表,再用for /F处理。
  3. 由于您一直启用delayed variable expansion!^ 可能会丢失。避免延迟扩展或明智地切换它可以防止这种情况发生。
  4. 当第二次执行脚本时,已经处理过的文件将被再次处理,因此下一个_将被替换。因此,建议定义排除此类文件的条件。例如,您可以使用 findstr 排除所有名称中已经包含 + 的文件。

这是一个可能的固定代码:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_ROOT=D:\path\to\target\location" & rem // (full path to target directory)
set "_MASK="*_*.*"                     & rem // (pattern to match files against)
set "_CHAR=_"                          & rem // (character to become replaced)
set "_REPL=+"                          & rem // (character used for replacement)
set "_FILT=^[^%_REPL%]*$"              & rem // (exclusion filter for `findstr`)

rem // Change into target directory:
pushd "%_ROOT%" && (
    rem // Iterate through all matching non-hidden and non-system files with exclusions:
    for /F "tokens=1* delims=%_CHAR% eol=%_CHAR%" %%I in ('
        dir /B /A:-D-H-S "%_MASK%" ^| findstr /I "%_FILT%"
    ') do (
        rem // Actually rename the currently iterated file (no delayed expansion here):
        if exist "%%I%_CHAR%%%J" ren "%%I%_CHAR%%%J" "%%I%_REPL%%%J"
    )
    rem // Return from target directory:
    popd
)

endlocal
exit /B

此脚本将跳过名称以 _ 开头的文件,以及第一次出现 _ 后紧跟另一个 _ 的文件。

【讨论】:

    猜你喜欢
    • 2020-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多