我有这个脚本,它通过尝试重命名目录来检查目录是否正在被使用,另外,检查它是否包含一些已知的临时文件。它工作得很好,除非它遇到一个带有所述临时文件的目录。
:: open each top dir for inspection and processing
for /d %%r in (*) do (
rem security
cd /d "%target%"
ren "%%r" "%%r(ctest)" || goto skip
ren "%%r(ctest)" "%%r" || goto skip
cd /d "%%r" || goto skip
dir /s *.!qb *.part *.dash* *.tmp >nul 2>nul && cd .. && goto skip
if defined verbose echo importing "%%~nxr"
rem call any scripts in the subdir with this script's own name
for /r "%~dp0%~n0\" %%s in (*.cmd) do call "%%s"
:skip
rem keep this (label can't be last)
echo done with "%%r"
)
不知何故,该行之后dir /s *.!qb *.part *.dash* *.tmp >nul 2>nul && cd .. && goto skip
脚本停止,并且我得到输出done with "%r"
,其中每个其他目录都显示目录名称%%r
,所以done with "directory name"
是预期的。
(
此批处理文件没有标签,标签在以匹配开头和结尾的命令块中不起作用,因为在执行任何命令行(包括FOR)
命令行)之前,首先解析整个命令块。请参阅:Windows 命令解释器 (CMD.EXE) 如何解析脚本?批处理文件名具有完整路径,但没有文件扩展名,在批处理文件的开头已经确定。原因请参见:为什么 %~dp0 引用的批处理文件路径有时会在更改目录时发生变化?
有问题的批处理文件使用当前工作目录,该目录由启动
cmd.exe
以处理批处理文件的进程在批处理文件之外定义。因此它可以是任何目录。此答案中的批处理文件用于%CD%\*
在当前工作目录中搜索非隐藏目录,这与 有所不同*
。找到的目录具有分配给循环变量的完整路径,G
而不仅仅是没有路径的目录名称。这在这里很重要,因为将当前工作目录路径推送到堆栈上,然后将当前工作目录更改为系统驱动器的根目录。其他命令行的FORpushd "%SystemDrive%\"
循环内需要具有当前进程目录名称的初始当前目录的完整路径。%CD%
通常扩展为不以反斜杠结尾的路径字符串。例外情况是当前目录是驱动器的根目录,在这种情况下%CD%
扩展为驱动器号、冒号和反斜杠。但是,C:\\*
这里没有问题,这要归功于 Windows 文件 I/O 的自动更正,如 Microsoft 文档中关于命名文件、路径和命名空间所述。在FOR循环中,当前目录被修改为系统驱动器的根目录,并将当前工作目录推送到堆栈上。我真的不明白
cd /d "%target%"
环境变量定义未知的原因。如果使用尚未包含在中的文件夹路径字符串定义,target
也可以使用。pushd "%target%"
target
"
然后尝试重命名找到的非隐藏子目录,方法是将名称附加
(ctest)
到目录名称上。如果由于目录或此目录的任何子目录或此目录或其子目录中的任何文件正在被任何正在运行的进程使用或由于缺少权限而失败,因此退出代码为,由于第一个IF条件, FOR1
循环内的大多数其他行将被忽略。成功重命名目录后,目录会立即重命名,而无需再次检查是否成功。它应该始终有效,否则结果就是由批处理文件导致的目录结构损坏。
使用命令PUSHD now 将当前目录再次更改为初始当前工作目录的当前处理的子目录。
执行命令DIR来搜索文件(不是目录),包括隐藏文件,如果不使用与
/A
当前目录的整个目录树中的通配符模式之一匹配的选项,则默认会忽略隐藏文件。仅当找不到与通配符模式之一匹配的文件时,第二个IF条件才为真。在这种情况下,将执行内部FOR
.cmd
命令,该命令以递归方式调用完全不同目录中所有具有名称的批处理文件,并调用批处理文件的完整路径和批处理文件的名称。我猜想该选项
/R
仅用于获取批处理文件名,并将完整路径分配给循环变量H
,并且引用的目录根本不包含子目录。如果我的假设正确,也可以将其用作内部FOR命令行:执行第二个PUSHD命令POPD,从堆栈中弹出最后推送的目录路径,并将该目录临时再次设为当前目录,即系统驱动器的根目录。
FOR循环内的最后两行命令行从堆栈中弹出初始当前目录路径,并在输出信息消息之前再次将该目录设为当前工作目录,然后FOR在初始当前工作目录中搜索下一个非隐藏目录。
要了解所使用的命令及其工作原理,请打开命令提示符窗口,在那里执行以下命令,并完整仔细地阅读每个命令显示的帮助页面。
call /?
... 解释%~dpn0
... 驱动器 + 路径 + 参数 0 的名称... 带有完整路径但没有文件扩展名的批处理文件名。cmd /?
dir /?
echo /?
endlocal /?
for /?
if /?
popd /?
pushd /?
rem /?
ren /?
set /?
…关于动态变量的解释CD
setlocal /?