使用批量延迟扩展在路径(感叹号!,胡萝卜^等)中出现特殊字符

时间:2016-03-31 14:37:36

标签: variables batch-file cmd path substitution

我环顾四周,找不到任何能让我的脚本在文件路径或文件中使用特殊字符(例如!;^)正常工作的内容名。

我的脚本确实有效,但前提是上述字符不在任何已扫描的文件夹或文件名中。如果任何文件夹或文件具有这些字符,则脚本会中断。我需要帮助找出如何使我的脚本在路径或文件名中使用特殊字符(如上所述)。这是我的剧本:

set srcdir=%~dp0%src

set desdir=%~dp0%des

setlocal EnableDelayedExpansion
for /r "%srcdir%" %%f in ("*.txt") do (
    set "subdir=%%~f"
    set "subdir=!subdir:%srcdir%=%desdir%!"
    echo !subdir!
    pause
)
endlocal

感谢您提供的所有帮助!

2 个答案:

答案 0 :(得分:3)

  1. 将所有路径放在""
  2. 之间
  3. 始终使用语法set "VAR=Value"
  4. 切换延迟展开:展开%%~F时,请将其停用;之后,启用它。
  5. 这是固定代码:

    setlocal DisableDelayedExpansion
    
    set "srcdir=%~dp0src"
    set "desdir=%~dp0des"
    
    for /R "%srcdir%" %%F in ("*.txt") do (
        set "subdir=%%~F"
        setlocal EnableDelayedExpansion
        set "subdir=!subdir:%srcdir%=%desdir%!"
        echo(!subdir!
        pause
        endlocal
    )
    endlocal
    

    只有存储批处理文件的目录不包含感叹号时,此方法才有效。如果确实如此,请告诉我......

    修订

    使用变量进行搜索和替换字符串的子字符串替换对于所有字符一般都不是安全的。

    想象一下你有这样的事情:

    echo(!VAR:%SEARCH%=%REPLACE%!
    

    这意味着用%SEARCH%替换%REPLACE%的每一次出现(以不区分大小写的方式)。

    但如果%SEARCH%包含=,则行为会发生变化:例如,%SEARCH%a=b%REPLACE%cd,立即展开的版本为!VAR:a=b=cd!,因此每个a都会被b=cd替换。

    *中的前导%SEARCH%更改了行为:将%SEARCH%之外的所有内容替换为%REPLACE%。 (在cource的路径中不能出现星号。)

    ~中的前导%SEARCH%将子字符串替换的行为更改为子字符串扩展,即字符位置长度给出的字符串部分的扩展;如果违反了语法,则会逐字地返回未展开的字符串!VAR:~a=b!,假设~ab分别是搜索和替换字符串。

    最后,如果%SEARCH%和/或替换包含!,则会将此视为延迟展开的结束!,因此可以看到!VAR:a!=b!作为!VAR:a!,这是无效的语法,将保持原样。

答案 1 :(得分:3)

设置变量时启用延迟扩展时,感叹号会被破坏。您可以通过等待延迟扩展直到检索变量值来避免这种情况。有时这需要一些杂技才能使它工作。在这种情况下,禁用延迟扩展可能更容易,并使用call来延迟扩展。

@echo off
setlocal

set "srcdir=%~dp0%src"
set "desdir=%~dp0%des"

for /r "%srcdir%" %%f in ("*.txt") do (
    set "subdir=%%~f"

    rem // use call to avoid delayed expansion and preserve exclamation marks
    call set "subdir=%%subdir:%srcdir%=%desdir%%%"

    rem // use set /p rather than echo to exploit quotation marks and preserve carets
    call set /P "=%%subdir%%"<NUL & echo;
    pause
)

或者如果您更喜欢延迟扩展,我想用一个技巧来切换一行的延迟扩展就是使用这样的for循环:

@echo off
setlocal

set "srcdir=%~dp0%src"
set "desdir=%~dp0%des"

for /r "%srcdir%" %%f in ("*.txt") do (
    set "subdir=%%~f"
    setlocal enabledelayedexpansion
    for %%I in ("!subdir:%srcdir%=%desdir%!") do endlocal & set "subdir=%%~I" & echo(%%~I
    pause
)