使用命令
DIR,带有参数
/b
和
"C:\Test Print Queue\"
,只输出指定目录中所有非隐藏文件和文件夹的名称,不包括路径。批处理文件执行时的当前目录是
C:\TestFoder
,与
C:\Test Print Queue
不同。因此,命令
MOVE无法找到存储在当前目录
C:\TestFoder
中不带路径指定的要移动的文件/文件夹,从而输出错误消息。
如果还使用了选项
/S
来搜索子目录,命令
DIR将输出带有完整路径的文件/文件夹名称。
一种解决方法是在
MOVE命令行中也指定源路径。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=C:\Test Print Queue"
set "DestinationFolder=C:\Test_Actual_Queue"
set "CreatedFolder="
if not exist "%DestinationFolder%\" (
md "%DestinationFolder%" 2>nul
if not exist "%DestinationFolder%\" (
echo Error: Failed to create folder "%DestinationFolder%"
goto EndBatch
)
set "CreatedFolder=1"
)
for /F "eol=| delims=" %%I in ('dir /A-D-H /B /ON "%SourceFolder%\*" 2^>nul') do (
echo Moving file "%SourceFolder%\%%I" ...
move "%SourceFolder%\%%I" "%DestinationFolder%\"
)
if defined CreatedFolder rd "%DestinationFolder%" 2>nul
:EndBatch
endlocal
pause
命令扩展在需要时会被显式启用,尽管默认情况下已启用。延迟环境变量扩展会被显式禁用,因为此任务不需要它。如果显式启用了延迟环境变量扩展,即使默认情况下未启用且此处不需要,有一个或多个感叹号的文件名的文件将无法在 FOR 循环内成功处理。请查看this answer以获取有关命令SETLOCAL和ENDLOCAL的详细信息。
如果目标文件夹不存在,则批处理文件首先创建该文件夹,并验证是否成功创建。
FOR 命令执行命令行
dir /A-D-H /B /ON "C:\Test Print Queue\*" 2>nul
在一个使用 cmd.exe /C
启动的后台命令进程中。
DIR 命令输出:
- 仅输出非隐藏文件,因为
/A-D-H
表示所有目录项没有设置为目录或隐藏属性;
- 裸格式显示,由于
/B
表示只显示文件名和扩展名,不包括文件路径;
- 按名称排序,因为
/ON
;
- 在目录
C:\Test Print Queue
中搜索匹配通配符模式 *
(任意文件)的文件。
源目录可能不存在或不包含符合条件的任何文件。使用将错误消息从处理程序 STDERR 重定向到设备 NUL 来抑制DIR在这些情况下产生的错误消息输出。
阅读Microsoft关于使用命令重定向运算符的文章,以了解2>nul
的解释。 重定向运算符>
必须在FOR命令行中用插入符号^
进行转义,以便在Windows命令解释器在执行嵌入的dir
命令行之前处理此命令行时将其解释为文字字符,该命令使用单独启动的后台命令进程执行。
此处使用选项/F
的FOR会捕获后台命令进程的STDOUT处理的所有内容,然后逐行处理捕获的文本。
FOR会忽略空行,但DIR使用的选项根本不输出空行。
默认情况下,以分号开头的行也将被FOR忽略。 文件名可以以分号开头。 因此,使用选项eol=|
将行结束字符从分号(默认)更改为文件名根本不可能包含的竖线。
FOR 会使用默认的分隔符空格和水平制表符将每一行拆分为子字符串 (令牌),并仅将第一个空格/制表符分隔的字符串赋给循环变量 I
。这种拆分行为在此处不是想要的,因此使用选项 delims=
定义了一个空白分隔符列表以禁用行拆分,并使得 I
始终被分配整个文件名,即使其中包含一个或多个空格。也可以使用 tokens=*
来获取整个行 (= 文件名) 赋给 I
。
对于由 DIR 输出的带有名称和扩展名但没有路径的文件,输出文件名并执行命令 MOVE 将文件移动到目标文件夹中,因为此处没有使用选项 /Y
,所以不会覆盖该文件夹中具有相同名称的文件。
最后,如果目标文件夹由批处理文件创建并且仍然为空,因为没有任何要移动的文件,则批处理文件将删除该文件夹。
另一种解决方案是将当前目录更改为源目录。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
cd /D "C:\Test Print Queue" || goto EndBatch
set "DestinationFolder=C:\Test_Actual_Queue"
set "CreatedFolder="
if not exist "%DestinationFolder%\" (
md "%DestinationFolder%" 2>nul
if not exist "%DestinationFolder%\" (
echo Error: Failed to create folder "%DestinationFolder%"
goto EndBatch
)
set "CreatedFolder=1"
)
for /F "eol=| delims=" %%I in ('dir /A-D-H /B /ON 2^>nul') do (
echo Moving file "%%I" ...
move "%%I" "%DestinationFolder%\"
)
if defined CreatedFolder rd "%DestinationFolder%" 2>nul
:EndBatch
endlocal
pause
如果命令
CD由于不存在源目录而无法更改当前目录,将输出众所周知的错误消息:
系统找不到指定的路径。
然后批处理文件跳转到标签
EndBatch
以恢复之前的环境,并暂停批处理文件执行,直到用户按任意键。
成功更改当前目录后,批处理文件继续执行,并使用命令
ENDLOCAL将初始当前目录
C:\ TestFoder
再次设置为执行批处理文件的命令进程的当前目录。
为了理解使用的命令及其工作原理,请打开命令提示窗口,在那里执行以下命令并非常仔细地阅读显示的每个命令的所有帮助页面。
cd /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
md /?
move /?
pause /?
rd /?
set /?
setlocal /?
'dir /b "C:\Test Print Queue\" ^| sort'
更改为'Dir /B/ON "C:\Test Print Queue"'
;使用Dir
可以输出已排序的内容,因此无需使用外部的sort.exe
。 - CompoPushD
或CD
从"C:\Test Print Queue"
工作,然后在括号内只使用'Dir /B/ON'
。 - Compo