将批处理文件中的波浪号(〜)替换为其他字符时,如何转义呢?

Tha*_*ama 2 cmd batch-file

该脚本可以将某些字符替换为文件名中的指定字符,但不适用于tilde ~

以下两个部分工作正常。

@echo off
setlocal enabledelayedexpansion
for %%a in (*_*) do (
    set file=%%a
    ren "!file!" "!file:_=A!"
)
for %%a in (*-*) do (
    set file=%%a
    ren "!file!" "!file:-=B!"
)
Run Code Online (Sandbox Code Playgroud)

但是这部分不起作用。

for %%a in (*~*) do (
    set file=%%a
    ren "!file!" "!file:~=C!"
)
Run Code Online (Sandbox Code Playgroud)

为什么更换~不起作用以及如何解决?

asc*_*pfl 5

您正在使用子字符串替换语法(例如!file:search=replac!),该语法不允许搜索字符串以开头~,因为那样的话,它将与子字符串扩展语法(例如!file:~pos,len!)混淆。

您可以做的是使用for /F以下~字符分割文件名:

for /F "tokens=1* delims=~ eol=~" %%I in ('dir /B /A:-D "*~*"') do (
    if not "%%J" == "" ren "%%I~%%J" "%%IC%%J"
)
Run Code Online (Sandbox Code Playgroud)

仅当存在单个~字符且不在第一个位置时,此方法才起作用。

如果~在任意位置有多个字符,它将变得更加复杂:

@echo off
for /F "delims= eol=|" %%F in ('dir /B /A:-D "*~*" ^| find "~"') do (
    set "FILE=%%F" & set "EXT=%%~xF"
    call :SUB NAME "%%~nF" C
    setlocal EnableDelayedExpansion
    ren "!FILE!" "!NAME!!EXT!"
    endlocal
)
exit /B

:SUB
    set "#RET=%~1"
    set "STR=%~2"
    set "CHR=%~3"
    set "LEFT=" & set "REST="
    if not defined STR goto :NEXT
:LOOP
    set "REST=%STR:*~=%"
    if "%REST%" == "%STR%" goto :NEXT
    for /F "delims=~ eol=~" %%E in ("_%STR%") do set "LEFT=%%E"
    set "STR=%LEFT:~1%%CHR%%REST%"
    goto :LOOP
:NEXT
    set "%#RET%=%STR%"
    exit /B
Run Code Online (Sandbox Code Playgroud)

该子例程:SUB在每个~循环中拆分文件名字符串,并通过替换~为指定字符来重建它。

需要过滤器| find "~"(以及if not "%%J" == ""第一种方法中的条件),因为dir还要匹配短文件名(通常包含一个~字符)。如果在系统上禁用了此类8.3文件名,则可能会删除这些其他代码部分(尽管它们不会造成损害)。