我有一个包含子目录的部署目录,每个部署都有一个子目录。我正在尝试编写一个批处理脚本,该脚本除其他外将对这些目录中的最新目录执行cd
。
我知道如何在bash
中进行此操作(也已经对here进行了解析),但是我不知道如何在Windows cmd
中完成相同的操作。谁能帮我吗?
答案 0 :(得分:2)
在批处理文件中,可以使用以下几行将其更改为具有最新修改日期的子目录:
@echo off
for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do cd "%%I" & goto DoneCD
echo No subdirectory found in: "%CD%"
:DoneCD
带有选项/F
的命令 FOR 使用%ComSpec% /c
和'
之间指定的命令行作为新的后台参数启动新的命令过程。因此,由 FOR 执行的操作具有通常的Windows安装路径:
C:\Windows\System32\cmd.exe /c dir * /AD /B /O-D 2>nul
由后台命令进程执行的DIR 使用指定的参数进行搜索
/AD
(属性目录)*
(全部)并输出
/B
而以裸格式显示,只是目录名称而没有路径,它们从未包含在"
中/O-D
在上次修改日期前的反向排序,而不使用选项/TC
(创建日期)或/TA
(最后访问日期),这意味着第一个是最新修改的目录,最后一个是最早的修改目录。DIR 的输出被写入以处理已启动的后台命令过程的 STDOUT 。
2>nul
将 DIR 输出的错误消息重定向到在当前目录中找不到任何目录时,将其从句柄 STDERR 重定向到设备 NUL 禁止显示此错误消息。
阅读有关Using Command Redirection Operators的Microsoft文章,以获取2>nul
的解释。当Windows命令解释器在执行命令之前处理此命令行时,重定向操作符>
必须在 FOR 命令行上使用脱字符号^
进行转义,才能被解释为文字字符。 FOR ,它将在后台启动的单独命令进程中执行嵌入式dir
命令行。
FOR 捕获由 DIR 编写的所有内容,以处理已启动命令过程的 STDOUT ,并在启动{{1}之后逐行处理此输出}终止。
FOR 会忽略由于 DIR 而不会在此处出现的空行,因为使用cmd.exe
会输出没有空行的目录名称列表。
FOR 默认情况下会使用常规空格和水平制表符作为分隔符,将一行拆分为子字符串(令牌)。在完成此子字符串拆分之后, FOR 将默认检查第一个子字符串是否以默认的行结束符/B
开始,在这种情况下,该行将像空行一样被忽略。否则, FOR 会将第一个空格/制表符分隔的字符串分配给指定的循环变量;
,并使用 CD 和 GOTO 。
例如,目录名称可以是I
,即以空格和分号开头并包含一个以上空格的目录名称。这样的目录名称将分为 ;Test Folder
(开头没有空格)和;Test
,然后由于<{1}}以分号开头而被 FOR 忽略。
因此,将行尾字符从默认分号重新定义为带有Folder
的竖线,根据Microsoft关于Naming Files, Paths, and Namespaces的文档,该文件或文件夹名称中不能包含该字符。并且在;Test
之后的选项参数字符串末尾使用eol=|
禁用了行拆分行为,该行定义了分隔符的空列表。因此, DIR 输出的目录名称被分配给循环变量delims=
,即使是非常不寻常的目录名称,也无需进行任何修改。
FOR 执行命令 CD ,该命令将当前目录更改为当前目录的最后修改的子目录,并执行下一个命令 GOTO 以继续执行标签行for /F
下一行的批处理文件处理。因此,在使用命令 GOTO 处理完第一个目录名称之后, FOR 循环执行已经中断。
当然可以在 FOR 命令行和标签行I
之后使用其他命令,而不仅仅是 ECHO 行报告没有子目录通过引用动态环境变量:DoneCD
就像在命令行上退出一样,可以在当前目录中找到该异常情况或错误情况下的批处理。
此 FOR 命令行和 GOTO 命令在 CD 之后不能退出 FOR 循环。 Windows命令提示符窗口。 Windows命令提示符窗口的解决方案是:
:DoneCD
在批处理文件中,此single line with multiple commands将写为
CD
或在其多行版本中更易读,并带有附加的set "DoneCD=" & (@for /F "eol=| delims=" %I in ('dir * /AD /B /O-D 2^>nul') do @if not defined DoneCD cd "%I" & set "DoneCD=1") & set "DoneCD="
@set "DoneCD=" & (@for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do @if not defined DoneCD cd "%%I" & set "DoneCD=1") & set "DoneCD="
首先,如果偶然定义了环境变量echo
。
下一步 FOR 如上所述,使用 DIR 运行@echo off
set "DoneCD="
for /F "eol=| delims=" %%I in ('dir * /AD /B /O-D 2^>nul') do (
if not defined DoneCD (
cd "%%I"
set "DoneCD=1"
)
)
if not defined DoneCD echo No subdirectory found in: "%CD%"
set "DoneCD="
,并处理具有最新修改日期的第一个输出目录。 IF 条件在最新目录上为true,因为在执行 FOR 之前绝对未定义环境变量。因此,执行命令 CD 将当前目录更改为最新的子目录。然后,使用值DoneCD
定义环境变量cmd.exe
。像使用DoneCD
一样,任何其他值也是可能的。这里重要的是,对于 DIR 输出的其他子目录,现在定义了环境变量1
,因此 IF 条件始终为false。因此,没有尝试将初始当前目录的当前子目录更改为此处不存在或偶然存在于该子目录中的子目录。
最后,如果在执行 FOR 的过程中完全定义了环境变量set "DoneCD=%%I"
,则会再次删除。
要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
DoneCD
DoneCD
cd /?
dir /?
echo /?
for /?
goto /?
...在最后的帮助页面上解释动态环境变量if /?
。