3

我想运行一个 .bat 脚本,该脚本创建一个文件并使用与其所在文件夹相同的名称保存它。我希望它在地图中启动并循环遍历子地图。我从下面的代码开始,并在其中一个子图中运行它。那行得通,我得到一个带有子图名称的文件。

FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI
ECHO Last segment = "%_LAST_SEGMENT_%"
echo.>%_LAST_SEGMENT_%.mp4
pause

所以现在我只需要把它放在一个 for 循环中。所以我做了下面的代码,这是行不通的。似乎%CD%是指我的父地图(子文件夹),.bat文件所在的位置,而不是我的子地图(video1、video2 等)。

Set Base=C:\Video\subfolders
FOR /R "%Base%" %%F IN (.) DO (
    PushD "%%F"
        FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI
        echo %CD%
        ECHO Last segment = "%_LAST_SEGMENT_%"
        echo.>%_LAST_SEGMENT_%.mp4
    PopD
)
Pause

输出:

C:\Video\subfolders>Set Base=C:\Video\subfolders
C:\Video\subfolders>FOR /R "C:\Video\subfolders" %F IN (.) DO (
PushD "%F"
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders>(
PushD "C:\Video\subfolders\."
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>(
PushD "C:\Video\subfolders\video1\."
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders\video1>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>(
PushD "C:\Video\subfolders\video2\."
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders\video2>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>(
PushD "C:\Video\subfolders\video3\."
 FOR / %I IN ("C:\Video\subfolders") DO SET _LAST_SEGMENT_=%~nxI
 echo C:\Video\subfolders
 ECHO Last segment = ""
 echo.   1>.mp4
 PopD
)
C:\Video\subfolders\video3>SET _LAST_SEGMENT_=subfolders
C:\Video\subfolders
Last segment = ""
C:\Video\subfolders>Pause
Press any key to continue . . .

我看到下面解释使用的链接,setlocal enabledelayedexpansion但我无法让它工作。

https://superuser.com/questions/503488/why-doesnt-cd-work-after-using-pushd-to-a-unc-path

任何意见,将不胜感激

4

2 回答 2

1

看起来你想要这样的东西:

@echo off
for /F "delims=" %%I in ('dir "C:\Video\subfolders\*" /AD-H /B /S 2^>nul') do (
    pushd "%%I"
    echo/>"%%~nxI.mp4"
    popd
)

pushd如下代码所示,这些命令popd并不是真正必要的:

@echo off
for /F "delims=" %%I in ('dir "C:\Video\subfolders\*" /AD-H /B /S 2^>nul') do (
    echo Directory is: %%I
    echo/>"%%I\%%~nxI.mp4"
)

命令FOR在一个单独的命令进程中运行,该进程cmd.exe /C在后台命令行中启动:

dir "C:\Video\subfolders\*" /AD-H /B /S 2>nul

命令DIR输出来处理这个后台命令进程的STDOUT

  • 由于选项而采用裸格式,由于选项而/B 仅具有完整路径的所有名称/S
  • /AD-H由于选项(属性目录而不是隐藏)的非隐藏目录
  • 在指定目录C:\Video\subfolders及其所有子目录中。

DIR在整个目录树中找不到任何目录条目时处理STDERR时输出的错误消息通过将其重定向到设备NULC:\Video\subfolders来抑制。

阅读有关使用命令重定向运算符的Microsoft 文章,了解2>nul. 当 Windows 命令解释器在执行命令FOR之前在后台启动的单独命令进程中执行嵌入式命令行时,重定向运算符>必须^FOR命令行上使用脱字符进行转义,以将其解释为文字字符。dir

FOR将输出捕获到已启动的命令进程的STDOUT并逐行处理此输出,忽略空行,默认情况下也忽略以分号开头的行,这两者都不会出现在此处。

FOR还会将每一行拆分为空格/制表符上的子字符串,并将仅将第一个空格/制表符分隔的字符串分配给指定的循环变量I。目录名称可以包含空格,因此delims=用于定义字符串分隔符的空列表,从而始终将当前从捕获的DIR输出I处理的完整限定目录名称分配给循环变量。

不带路径的目录名被引用%%~nxI为最后一个反斜杠后的字符串。目录名称也可以包含点状folder.name或以点状开头,.FolderName尽管两者在 Windows 上都不常见。出于这个原因,有必要使用%%~nxI(name and extension) 而不仅仅是%%~nI因为FOR不验证引用的字符串%%I是文件名还是目录名。

%%~nI如果有任何反斜杠(斜杠),则引用最后一个之间的字符串\(或/为了与Linux路径的兼容性,所有第一个都替换为如果没有点,则确定名称字符串的开头或字符串的结尾。引用以在最后一个目录分隔符后找到的最后一个点开头的字符串。因此,分配给循环变量的字符串不能是真正存在的文件/文件夹的文件/文件夹名称,尽管这里是这种情况。如果包含以( 或\\/.%%~xII%%~nxII\/)。

不要将可以使用不带或带修饰符的循环变量引用的字符串分配给环境变量,因为这将需要使用延迟扩展,正如在命令提示符窗口中运行时命令SET输出的帮助所解释的那样set /?

要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • dir /?
  • echo /?
  • for /?
  • popd /?
  • pushd /?

另请参阅 DosTips 论坛主题ECHO。无法提供文本或空行 - 而是使用 ECHO/

有问题的第二个批处理文件代码不起作用,因为没有使用延迟扩展或避免使用在命令块内定义/修改并使用语法在同一命令块内引用的环境变量%variable%。Windows 命令处理器在第一次执行外部FOR之前解析从 第一个FOR到匹配cmd.exe的整个命令块。请参阅Windows 命令解释器 (CMD.EXE) 如何解析脚本?此命令块中的所有引用在此预处理阶段已被引用的环境变量的当前值替换。所以代码最终在迭代外部FOR时执行()%variable%不再包含任何%variable%环境变量引用,因为它可以cmd.exe在执行命令行之前在命令行输出中看到。

于 2018-12-05T16:42:08.790 回答
0

虽然Mofi 的回答解决了 OP 的问题,但它实际上并没有回答最初提出的问题。

%CD%在循环中不起作用的原因FOR是您需要启用“延迟扩展

例如:

SETLOCAL EnableDelayedExpansion
FOR %%i in (foo bar) DO (
    pushd %%i
    echo CD with delayed expansion: !CD!
    echo CD without it: %CD%
)

假设运行时存在“foo”和“bar”目录,您应该看到它!CD!给出了正确的路径。

更多示例:批处理文件中延迟扩展的示例

于 2020-07-15T17:48:39.160 回答