【问题标题】:For /f loop process filename ampersand symbolFor /f 循环处理文件名和符号
【发布时间】:2013-06-29 19:36:50
【问题描述】:

我有一个处理删除文件的 for 循环,但我最近遇到了一个文件名包含 & 的文件,我收到了一个错误 & was unexpected at this time。所以我不确定它为什么这样做,我把它用引号括起来。

文件名示例:[This_&_That]_FileName.txt

小例子:

FOR /F "tokens=* delims=;" %%P in ("%*") do call :LOOP %%P

:LOOP

if '%1'=='' goto :endloop

echo %1

pause

....

:endloop

exit

这适用于空格,但使用& 符号会崩溃。我必须从 cmd 运行 .bat 文件,并将文件名作为参数,才能看到错误。

我已尝试启用延迟扩展 - 就像在这篇文章中一样,要么我没有正确执行,要么它对我不起作用:stackoverflow post

【问题讨论】:

    标签: windows batch-file parameters filenames


    【解决方案1】:

    Windows 资源管理器错误

    如果文件名包含空格字符,则资源管理器不会用双引号将其括起来以进行拖放操作。因此,您无法在批处理文件中正确处理带有与号 (&) 的此类文件名。

    假设您有以下批次script.bat

    @ECHO Off &SETLOCAL
    :loop
    ECHO "%~1"
    SHIFT /1
    IF NOT "%~1"=="" GOTO :loop
    pause
    

    制作两个文件,例如。在命令行上:

    type nul>"This_&_That.txt"
    type nul>"This & That.txt"
    

    现在转到资源管理器,将两个文件拖放到您的script.bat
    让我们看看会发生什么:

    "C:\TEST\This & That.txt" "C:\TEST\This_" 按任意键继续 。 . .


    Extended explanation.

    【讨论】:

    • 谢谢,但是 for 语句仍然没有将正确的名称传递给子例程,它仍然在“&”符号处中断
    • 也许,但我不知道如何应用所有这些......作为 1,它不仅仅是一个 .txt 或 .csv 文件,它也适用于 1 个或多个文件我正在删除 bat 文件,说明我为什么使用 /f %*.,那么我该如何实现它以便我可以拖放任何文件,它会将带有或不带有 & 符号的文件名传递给子程序
    • 这是一张无法运行的图片,test.bat 在我的桌面上,已经从结果中显示的位置删除了文件,[link]i.snag.gy/fnGBj.jpg
    • 哇——我什至没有想到会有这样的错误——谢谢你发现我只需要重命名文件。再次感谢。
    【解决方案2】:

    您不需要子例程 :LOOP。你能忍受 %%P 周围的引号吗?

    FOR /F "tokens=* delims=;" %%P in ("%*") do echo."%%P" & pause
    

    【讨论】:

    • 感谢您的快速响应,我想我需要子例程,因为我不只是打印文件名......它只是这里的替代品......但我不在乎报价只要有效。如果我回显我当前的 %1 (没有 & 的文件),路径和文件周围已经有引号......这就是我认为 %* 周围的引号正在做的事情。所以在 %%P 周围加上引号不会添加另一组引号并使其不可读?
    • 是的,在 %%P 周围添加引号似乎几乎会使 %* 周围的引号无效,并且无法处理带有空格的路径/文件名。
    • 你能把你有的东西贴出来吗?我不知道你现在在用什么(我的代码没有子程序或者你的有它)。
    • 我想如果你 echo.%%P 而不是调用 :LOOP 你会看到它没有引号。
    • 我正在使用 sub: FOR /F "tokens=* delims=;" %%P in ("%*") do call :LOOP %%P :LOOP if "%1"=="" goto :endloop REM ----VARS----- set "f=%~n1" set fn=%f: =_% set var=%tempd%\%fn%_new.txt set var2=%tempd%\%fn%_new2.txt echo "%1" echo。回声 %var% 回声。 echo %var2% pause 这是一些但在继续
    【解决方案3】:

    在这一行:

    if '%1'=='' goto :endloop
    

    %1 的值不是用引号括起来的,而是用撇号括起来的。改成这样:

    if "%1"=="" goto :endloop
    

    当然,您还需要在子程序中的echo 命令和调用程序中的%%P 周围将%1 括在引号中,但是在这种情况下,%1 的值将带有引号已经

    【讨论】:

    • 谢谢 - 愚蠢的错误,但这解决了错误......但使用上述示例处理的文件名并回显 %1 结果:drive\path\[This_
    • 并回显“%1”会导致“drive\path\[This_”
    • 就像我上面所说的,将 %1 放在子例程中的引号中仍然会导致文件名被完全处理,它会在 & 符号所在的位置停止。
    • @Aacini 如果文件名被引用,该术语应为“%~1”。
    • @foxidrive:不完全是。如果 %%P 以这种方式用引号括起来:call :LOOP "%%P",那么 %1 总是用引号括起来,而 %~1 不是,所以程序应该在每种情况下使用它需要的版本。但是,正如 Endoro 在他的回答中解释的那样,没有任何修改可以解决这个问题。
    【解决方案4】:

    Hmmmm....因为我认为您是我们将您的代码与子例程一起使用...我将忽略有关我的单行建议的评论,而无需 CALL。我们应该选择一个问题并解决它,而不是来回反弹。在您的示例中,您需要引用 %%P。子程序中的典型做法是执行“%~1”。波浪号会删除引号,如果需要,“”会再次将它们放回去。有时它们不是必需的,但在您的情况下它们是必需的。您的 CALL 使用:LOOP,您的示例使用:ENCODE。我将恢复到 :LOOP。

    FOR /F "tokens=* delims=;" %%P in ("%*") do call :LOOP "%%P"
    
    :LOOP
    if "%~1"=="" goto :endloop
    REM ----VARS-----
    set "f=%~n1"
    set fn=%f: =_%
    set var=%tempd%\%fn%_new.txt
    set var2=%tempd%\%fn%_new2.txt
    echo "%~1"
    echo.
    echo %var%
    echo.
    echo %var2%
    pause
    REM this is some but in continues on
    echo.done & PAUSE
    

    【讨论】:

    • 不...仍然通过将 C:\Users\Jim\Desktop\Folder\[This_&_That]_FileName.txt 放到 bat 文件中,结果来自上面的确切代码,“C: \Users\Jim\Desktop\Folder\[This_" "C:\Users\Jim\Desktop\Folder\tempd"\[This__new.txt "C:\Users\Jim\Desktop\Folder\tempd"\[This__new2.txt按任意键继续...
    • 啊……您需要其他 3 个 SET 命令的引号。设置 "fn=%f: =_%" 设置 "var=%tempd%\%fn%_new.txt" 设置 "var2=%tempd%\%fn%_new2.txt"
    • 我现在不用担心这些,因为 echo "%~1" 是不正确的,这意味着无论如何这些都是不正确的。但谢谢这可能会解决未来的问题
    猜你喜欢
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多