[英]For /d /r loop not traversing sub-directories for finding desired directory recursively in Batch/CMD script
如问题标题中所述,如果传递给脚本的参数是 Chrome,我有一个 Batch/CMD(OS: Windows 10 64Bit) 脚本来遍历%LocalAppData%
内的子文件夹,并递归查找并列出所有包含单词Cache的文件夹position。
我想出的依赖for /d /r
循环的脚本是这样的:
@echo off && setlocal EnableDelayedExpansion
if /i "%1" equ "chrome" (
set "subPath0=\Google"
set "subPath1=\User Data"
for /d /r "%LocalAppData%!subPath0!\%1" %%i in (*Cache*) do (
echo "%%i"
)
) else (
for /d /r "%Appdata%\%1" %%i in (*Cache*) do (
echo "%%i"
)
)
但无论我是否像(*Cache*^)
那样转义for
循环内的右括号,上述循环都没有递归列出任何*Cache*
目录,即使路径内实际上有Cache文件夹(其中for
循环正在运行)在User Data
文件夹中。
那么谁能指出我在这里做错了什么并帮助解决这个问题?
注意:我知道 Powershell 是 Batch/CMD 的不错选择,但这应该是较大脚本的一部分,所以如果在 Batch/CMD 中提出建议/修复,将不胜感激。
从FOR
命令中删除路径并改用 PUSHD。
@echo on
setlocal EnableDelayedExpansion
if /i "%1" equ "chrome" (
set "subPath0=\Google"
set "subPath1=\User Data"
pushd "%LocalAppData%!subPath0!\%~1"
for /D /R %%i in (*Cache*) do (
echo "%%i"
)
popd
) else (
pushd "%Appdata%\%1"
for /d /r %%i in (*Cache*) do (
echo "%%i"
)
popd
)
为什么不将其简化为一个FOR
命令?
@echo on
setlocal EnableDelayedExpansion
if /i "%~1" equ "chrome" (
set "subPath0=\Google"
set "subPath1=\User Data"
set "searchpath=%LocalAppData%!subPath0!\%1"
) else (
set "searchpath=%Appdata%\%~1"
)
for /d /r "%searchpath%" %%i in (*Cache*) do echo "%%i"
我强烈建议使用:
@echo off & setlocal EnableExtensions DisableDelayedExpansion
if /I not "%~1" == "chrome" goto SearchAppdata
for /D /R "%LocalAppData%\Google\%~1" %%i in (*Cache*) do echo "%%i"
goto EndBatch
:SearchAppdata
for /D /R "%Appdata%\%~1" %%i in (*Cache*) do echo "%%i"
:EndBatch
endlocal
所有变化的解释:
命令echo off
永远不会失败,因此在第一行使用无条件运算符&
代替条件运算符&&
。 有关详细信息,请参见使用 Windows 批处理文件的单行多命令。
批处理文件需要启用命令扩展。 出于这个原因,建议显式启用命令扩展并且不要依赖于在批处理文件之外启用。
明确不使用延迟扩展,因为这会导致%~1
、 %%i
、 %LocalAppdata%
或%Appdata%
扩展为具有一个或多个的字符串!
将感叹号解释为文字字符将不再正确处理。
字符串比较运算符==
用于比较两个字符串,而不是 integer 比较运算符equ
也适用于字符串,但在一些罕见的用例中与字符串比较运算符不同。 有关详细信息,请参阅Windows 批处理文件中与 NEQ、LSS、GTR 等等效的符号。
传递给批处理文件的第一个参数字符串将在开头和结尾删除"
,如果两边都包含在"
中,否则批处理文件处理由于严重的语法错误已经在第二行停止。 如果有人用google"
之类的东西运行批处理文件,仍然会发生这种情况,即参数字符串的末尾有一个双引号,但开头没有双引号。也可以通过额外的方法来处理这个极其罕见的用例命令行,但这里不应该真的有必要,因为这是程序或用户启动批处理文件的语法错误。
命令GOTO用于避免命令块,这使得可以引用所有环境变量而不会延迟扩展。
命令FOR不支持在/R
之后指定的路径内延迟扩展。 这是 DosTips 论坛主题Limitation in for /r command 中记录的此命令的一个已知问题。 解决方案是避免在/R
之后指定的目录路径字符串内延迟扩展。
可以在CD之前使用(不适用于 UNC 路径)或PUSHD (也适用于启用了命令扩展的 UNC 路径)和循环之后的POPD 。 或者使用由另一个在后台启动的命令进程执行的命令DIR ,它的优点是还可以找到包含名称中的字符串cache
的隐藏目录, for /D
忽略,而for /R
也遍历隐藏目录。
@echo off & setlocal EnableExtensions DisableDelayedExpansion
if /I not "%~1" == "chrome" goto SearchAppdata
for /F "delims=" %%i in ('dir "%LocalAppData%\Google\%~1\*Cache*" /AD-L /B /S 2^>nul') do echo "%%i"
goto EndBatch
:SearchAppdata
for /F "delims=" %%i in ('dir "%Appdata%\%~1\*Cache*" /AD-L /B /S 2^>nul') do echo "%%i"
:EndBatch
endlocal
在这种情况下,由于选项/AD-L
(属性目录,但不是属性链接),重解析点(目录连接、符号链接)被显式忽略,有关 Windows 上的链接的更多信息,请参阅SS64 - MKLINK。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.