【问题标题】:How to get rid of enclosing double-quotes in the expanded `forfiles` variables?如何摆脱扩展的“forfiles”变量中的双引号?
【发布时间】:2015-12-06 03:36:51
【问题描述】:

forfiles 命令建立了几个变量,由前导 @ 表示,它们将有关当前迭代项的数据返回到循环体。

所有与被迭代项的路径和名称相关的变量都返回""所包围的值。它们是:@file@fname@ext@path@relpath

那么:如何去掉封闭的双引号?


例如,以下代码返回给定根目录中文本文件的相对路径:

forfiles /P "C:\root" /M "*.txt" /C "cmd /C echo @relpath"

假设C:\root包含两个文件file1.txtfile2.txt,输出将是:

".\file1.txt"
".\file2.txt"

但是,我想要不带 "" 的文件列表。

我正在使用 Windows 7 64 位。

【问题讨论】:

    标签: batch-file for-loop cmd quotes


    【解决方案1】:

    一种方法是在forfiles 中嵌套for %I 循环并使用%~I 扩展——在命令提示符窗口中使用此代码:

    forfiles /P "C:\root" /M "*.txt" /C "cmd /Q /C for %I in (@relpath) do echo %~I"
    

    要在批处理文件中使用该代码,您必须将 %-signs 加倍:

    forfiles /P "C:\root" /M "*.txt" /C "cmd /Q /C for %%I in (@relpath) do echo %%~I"
    

    返回的文件列表将是(依赖于原始问题中的示例文件):

    .\file1.txt
    .\file2.txt
    

    另一种变体是将另一个forfiles 嵌套在初始字符串的主体中,因为forfiles 删除了给定字符串中的(非转义)双引号,例如/C 之后的命令行:

    forfiles /P "C:\root" /M "*.txt" /C "cmd /C forfiles /P @path\.. /M @file /C \"cmd /C echo @relpath\""
    

    或者(加倍的内部forfiles 是故意的,这可以解决一个错误——参见this post):

    forfiles /P "C:\root" /M "*.txt" /C "forfiles forfiles /P @path\.. /M @file /C \"cmd /C echo @relpath\""
    

    内部forfiles 将仅枚举一项,即外部循环传递的一项。由于@relpath在执行内部循环时已经展开,因此引号被删除,因为它们没有被转义。

    所以返回的文件列表看起来像(再次从原始问题中获取示例文件):

    .\file1.txt
    
    .\file2.txt
    

    行之间的额外换行符由forfiles 生成。您可以使用重定向来避免这种情况(关闭forfiles 输出,但在控制台窗口中仅显示echo 输出):

    > nul forfiles /P "C:\root" /M "*.txt" /C "cmd /C forfiles /P @path\.. /M @file /C 0x22cmd /C > con echo @relpath0x22"
    

    【讨论】:

    • 这似乎对我不起作用。 FORFILES /P "E:\archives" /M *.* /S /D -1 /C "cmd /Q /C FOR %I IN (@path) DO ECHO %~I" 只是给了我一个“~我在这个时候出乎意料。”每一行都有错误。
    • 您是否像我在回答的第一句话中所说的那样将%-signs 加倍了?请注意,仅当您直接在命令提示符窗口中尝试代码时才能使用单个 %-signs...
    • 啊!完全错过了。我已经投了反对票,并且会改变我的投票,但在编辑之前不允许这样做。您能否在答案中加粗该评论,或者在其下方为批处理文件制作另一个示例,以便它脱颖而出并允许我投票?
    • 虽然对我没用,但我想在目标调用中同时使用 \@file 和 \@path 对文件很有用,因为我可以同时获得这两个。我收到“找不到指定的文件”的相同错误,并且他们的所有示例都使用 echo
    • @path 上嵌套一个for 循环应该可以工作:for %I in (@path) do echo "%~I" = @path, "%~nxI" = @file
    【解决方案2】:

    我删除这样的引号:

    @ECHO OFF
    GOTO START
    
     usage: 
     script.bat "*.txt" "c:\Documents"
     script.bat "*.txt"
     script.bat
     If no arguments added it will crawl the current directory with wildcard mask (*)
     Avoid root directory (c:\) because too many sub directories for the output console.
    
     :START
    IF "%~2"=="" (SET "_FD=%CD%") ELSE (SET "_FD=%~2")
    IF "%~1"=="" (SET "_MA=*") ELSE (SET "_MA=%~1")
    
    SETLOCAL ENABLEDELAYEDEXPANSION
    FOR /F "usebackq delims=" %%A in (
            `forfiles /p %_FD% /s /m %_MA% /C "cmd /c ECHO @relpath"`
        ) DO (
        SET "myfile=%%~A"
        ECHO !myfile:~2!
    )
    ENDLOCAL   
    GOTO :EOF
    

    结果:

    thumbnails\A0-1.jpg
    thumbnails\new folder\img.jpg
    

    【讨论】:

    • 这对我有用,谢谢!我编辑了我的一点。在ECHO !myfile:~2! 行上,我将我的更改为ECHO !myfile! 以获得不带引号的完整路径。
    • 再次只使用@relpath 并且只是回显而不是调用使用它的东西..
    猜你喜欢
    • 2012-01-25
    • 2012-10-28
    • 2014-06-19
    • 2018-03-30
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    相关资源
    最近更新 更多