如何使批处理文件遍历子目录



一些上下文: 我从大约 100 张以 AFSM-DDMMYY_doe-john 格式命名的 jpg 图像开始.jpg然后仅使用以下脚本根据其名称将它们分类到文件夹中:

文件夹创建者.bat

@echo off &setlocal
for /f "delims=" %%i in ('dir /b /a-d *.jpg') do (
set "filename1=%%~i"
setlocal enabledelayedexpansion
set "folder1=!filename1:~12,-4!"
mkdir "!folder1!" 2>nul
move "!filename1!" "!folder1!" >nul
)

然后,我删除文件名的第_last部分,以便图像最终采用AFSM-DDMMYY格式.jpg 这是使用以下脚本完成的:

名称去除剂.bat

@echo off &setlocal
for /f "delims=" %%i in ('dir /b /a *.jpg') do (
set "filename1=%%~i"
setlocal enabledelayedexpansion
set "name1=!filename1:~0,11!"
ren "!filename1!" "!name1!.jpg"
)

生成的文件夹最终被命名为doe-john,其中包含AFSM-DDMMYY.jpg图像。为此,这些文件夹都位于一个公共文件夹中。这很好用,但我希望能够从公共文件夹中运行 nameremover.bat以便它在所有 doe-john 文件夹中运行自身,而不是我必须将其移动到每个文件夹,然后单独运行它在那里。提前谢谢你。

简单的方法是创建一个目录来包含批处理文件 - 常用名称是batchbelfry,并将该目录名包含在path变量中。这样,无论您的当前目录如何,都可以执行目录中的任何批处理文件。

哦 - 顺便说一句:你为什么不直接使用

move "!filename1!" "!folder1!!filename1:~0,11!!filename1:~-4!" >nul

在你的第一批?


当您指定可执行文件的路径(例如c:somedirectoryexecutable.exe)时,这将是将要执行的文件。但是,如果您省略该目录而只是执行executable.exe则尝试在当前目录中查找该文件。如果此操作失败,则检查环境变量path,并运行在path上找到的第一个匹配的可执行文件。

因此,如果您修改path以包含诸如c:batch之类的目录,那么如果c:batch目录中存在executablename.exe则运行可执行文件的任何尝试都将运行它。

可执行文件有多种形式,其中最重要的是.bat.cmd.exe,可以使用其基本名称调用,因此执行fred将在每个.(当前目录)和%path%(包含分号分隔的目录列表的环境变量)中找到fred.batfred.cmdfred.exe

您可以使用Windows更改路径,但是像path editor(Google)这样的第三方实用程序使其变得容易。

所以 - 您需要做的就是建立一个目录来包含您的批处理文件(您已经在使用mkdir命令在发布的批处理中执行此操作(尽管使用md更常见,它是mkdir的同义词))然后将批处理移动到该目录,您可以使用其基本名称运行批处理, 无论您的当前目录恰好在哪里。

实际上,我在那里存储的不仅仅是批次 - 我也将其用于我所有的实用程序.exe- 例如sed

分析你的代码,

@echo关闭和设置本地

&级联这两个命令。@echo off将命令回显offsetlocal建立一个本地环境,以确保对环境的任何更改(创建或删除的变量等)在批处理结束时恢复到其原始状态。请注意,这不会恢复添加/删除/更改/移动的文件 - 只是环境变量。

对于/f "delims=" %%i in ('dir/b/a-d *.jpg') do (

执行dir命令以查找所有.jpg文件;仅命名,不查找目录名称。将此列表放入内存,就好像它是一个文件一样。逐行"读取"列表,并依次将每行的内容分配给%%i

设置"文件名1=%%~i">

将环境变量filename1设置为%%i=dir行的内容。

设置本地启用延迟扩展

NEST 一个新的本地环境,但delayedexpansion调用此环境,因此!var!表示"var的当前值",而%var%表示"遇到for**时var的值**

设置"文件夹1=!文件名1:~12,-4!">

folder1设置为当前filename1,从第 13 个字符(计数从"字符 0"开始)到末尾的第 4 个字符。

Mkdir "!folder1!"2>无

创建该目录,抑制和错误消息(如"它已经存在")

移动"!文件名 1!"!文件夹1!">无

将文件移动到新目录。由于"folder1!" is a directory, the file will be moved into that directory. If it didn't exist, the移动would move the file to a **file** named"!文件夹1!`

)

。和code block的结束,由几行前do后的(开始。

谨慎

setlocal建立嵌套的本地环境。这些是有限的。您应该在move命令之后放置一个endlocal命令以结束本地环境,因此您的代码应该为每个处理的文件创建和删除本地环境。

因此,将move替换为我提倡的move,更改将意味着移动的目的地是 [folder1中的目标目录 \filename1的前 12 个字符 +filename1中的最后 4 个字符]

这将消除nameremover过程。

@echo off &setlocal
for /f "delims=" %%i in ('dir /b /a-d *.jpg') do (
set "filename1=%%~i"
setlocal enabledelayedexpansion
set "folder1=!filename1:~12,-4!"
mkdir "!folder1!" 2>nul
move "!filename1!" "!folder1!!filename1:~0,11!!filename1:~-4!" >nul
ENDLOCAL
)

应该在不执行"名称删除器"步骤的情况下进行处理。在进行path更改后,将其放入batch目录中,无论您在系统上的任何地方,包括登录到其他驱动器,都应该能够直接从提示符运行代码。


要建立菜单,常规方法是:

:again
cls
echo 1. do thing 1
echo 2. do thing 2
echo 3. do thing 3
echo q  quit
choice /c 123q /m please choose...
if errorlevel 4 goto :eof
if errorlevel 3 call batch3&goto again
if errorlevel 2 call batch2&goto again
if errorlevel 1 call batch1&goto again
goto again

在提示符下choice /?将生成有关choice如何工作的指南。

errorlevel根据字符位置设置/c激活的密钥字符串。

由于如果errorlevel为 n或大于 n,则if errorlevel n为 true,因此必须按反向值顺序构造代码。

要执行的代码可能会更改errorlevel的值。 因此,在执行子公司后需要goto批处理以确保从batch3返回,说不被解释 其余if errorlevel语句。

最新更新