运行批处理文件时系统找不到指定的路径

4
我正在尝试将文件从一个文件夹移动到另一个文件夹,但我始终会收到这个异常信息:“系统找不到指定的路径”。
以下是我的批处理命令代码:
setlocal EnableDelayedExpansion
set destinationFolder=C:\Test_Actual_Queue
rem Create an array with filenames in right order
for /f "tokens=*" %%f in ('dir /b "C:\Test Print Queue\" ^| sort') do (
 echo %%f
 move %%f %destinationFolder%
)
pause

我能够在控制台中对文件名进行排序和显示,但是当我尝试移动到目标文件夹时,我遇到了上述异常。

两个文件夹路径都是正确的。

我尝试进行调试,这是我在控制台中得到的数据:

C:\TestFoder>setlocal EnableDelayedExpansion

C:\TestFoder>set destinationFolder=C:\Test_Actual_Queue

C:\TestFoder>rem Create an array with filenames in right order

C:\TestFoder>for /F "tokens=*" %f in ('dir /b "C:\Test Print Queue\" | sort') do (
echo %f
 move %f C:\Test_Actual_Queue
)

C:\TestFoder>(
echo data1.Print_Job
 move data1.Print_Job C:\Test_Actual_Queue
)
data1.Print_Job
The system cannot find the file specified.

C:\TestFoder>(
echo data2.Print_Job
 move data2.Print_Job C:\Test_Actual_Queue
)
data2.Print_Job
The system cannot find the file specified.

我在这里做错了什么?

期待您的解决方案。提前致谢。


2
因为for变量只输出文件名而不是文件夹。您的批处理文件的工作目录不同,因此它正在尝试在当前工作目录中查找该文件。您需要在move命令中包含输入文件夹路径。 - Squashman
你知道输入文件夹的路径。你在DIR命令中已经有它了! - Squashman
是的,我明白了。我已经在for循环中连接了路径,例如:C:\Test Print Queue%%f,现在它可以工作了。感谢Squashman的建议。 - Roy
2
'dir /b "C:\Test Print Queue\" ^| sort'更改为'Dir /B/ON "C:\Test Print Queue"';使用Dir可以输出已排序的内容,因此无需使用外部的sort.exe - Compo
1
可能值得先使用PushDCD"C:\Test Print Queue"工作,然后在括号内只使用'Dir /B/ON' - Compo
显示剩余2条评论
1个回答

1
使用命令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以获取有关命令SETLOCALENDLOCAL的详细信息。

如果目标文件夹不存在,则批处理文件首先创建该文件夹,并验证是否成功创建。

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命令行之前处理此命令行时将其解释为文字字符,该命令使用单独启动的后台命令进程执行。

此处使用选项/FFOR会捕获后台命令进程的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 /?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接