在嵌套循环中使用变量%% f的批处理文件失败

时间:2017-10-02 16:27:21

标签: batch-file

我很困惑这里发生了什么。它应该将从docs找到的所有docx复制到工作目录。但由于某种原因,for循环中的%% f显示为%f。我做了一个回声,它打印出文件夹就好了。同样的事情也发生在%% r和%r上。我是不是写错了?

set filepath=%1
for /f %%f in ('dir /ad /b %filepath%') do (
if exist "%filepath%\%%f\docs" (
for /r %filepath%\%%f\docs %%r in (*.docx) do (
echo %%f
copy %%r "%cd%\edited"
)
)
)

输出

if exist "C:\Documents\WordDocs\Data1\docs" (for /R C:\Documents\WordDocs\%f\docs %r in (*.docx) do ( 
echo Data1
copy %r "C:\Users\admin\Desktop\Test"
) ) )

2 个答案:

答案 0 :(得分:2)

for command(与if command一样)比其他命令更早解析。目前,for%%f变量引用尚未被识别。因此,for /R无法使用包含for变量引用的根路径,例如%%ffor /F的选项字符串也是如此。您也不能使用delayed expanded variable代替%%f

手头脚本最简单的解决方法是在"%filepath%\%%f\docs"循环之前使用pushd for /R,然后在popd之后使用for /R。{{1}使用它的默认根,即当前工作目录,它刚刚由pushd设置;前一个由popd恢复。以下是我的意思:

set "filepath=%~1"
for /F %%f in ('dir /A:D /B "%filepath%"') do (
    if exist "%filepath%\%%f\docs" (
        pushd "%filepath%\%%f\docs"
        for /R %%r in ("*.docx") do (
            echo/%%f
            copy "%%~r" "%cd%\edited"
        )
        popd
    )
)

另一种更复杂的方法是将for /R循环移动到子例程中,由call command调用它并将根路径作为argument传递,如这样:

set "filepath=%~1"
for /F %%f in ('dir /A:D /B "%filepath%"') do (
    if exist "%filepath%\%%f\docs" (
        call :SUB "%filepath%\%%f\docs"
    )
)
goto :EOF

:SUB
for /R "%~1" %%r in ("*.docx") do (
    echo/%%f
    copy "%%~r" "%cd%\edited"
)
goto :EOF

参考这篇文章:How does the Windows Command Interpreter (CMD.EXE) parse scripts?

答案 1 :(得分:1)

此版本不使用For /R

For /F "Delims=" %%A In ('Dir/B/AD-L "%~1"') Do If Exist "%~1\%%A\docs\" (
    For /F "Delims=" %%B In ('Dir/B/S/A-D-L "%~1\%%A\docs\*.docx"'
    ) Do Echo=Copy "%%~B" "%CD%\edited")
Pause

如果您对cmd窗口中的输出感到满意,记住未编辑您的目的地路径,请删除第3行的第4行和Echo=