Команда DIR с аргументами /b
и "C:\Test Print Queue\"
выводит только имена всех не скрытых файлов и каталогов в указанном каталоге без пути. Текущий каталог при выполнении командного файла - C:\TestFoder
, который отличается от C:\Test Print Queue
. По этой причине команда MOVE не может найти файл / каталог для перемещения, сохраненный в C:\Test Print Queue
, указанном без пути в текущем каталоге C:\TestFoder
, и выводит сообщение об ошибке.
Команда DIR выведет имена файлов / папок с полным путем, если дополнительно опция /S
используется для поиска также в подкаталогах.
Одно из решений - указать исходный путь также в командной строке 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 /F
, хотя включены по умолчанию. Задержка раскрытия переменных среды явно отключена, поскольку она не требуется для этой задачи. Файлы с одним или несколькими восклицательными знаками в имени файла не могут быть успешно обработаны в цикле FOR , если отложенное расширение переменной среды включено явно, хотя не включено по умолчанию и здесь не требуется. Прочитайте этот ответ для получения подробной информации о командах 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
в соответствии с шаблоном подстановки *
(любой файл).
Возможно, что исходный каталог вообще не существует или не содержит файлов, соответствующих критериям. Сообщение об ошибке, выводимое в этих случаях с помощью DIR , подавляется путем перенаправления его с дескриптора STDERR на устройство NUL .
Прочтите также статью Microsoft о Использование операторов перенаправления команд для объяснения 2>nul
. Оператор перенаправления >
должен быть экранирован с помощью символа вставки ^
в командной строке FOR , чтобы интерпретироваться как литеральный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR , которая выполняет встроенную командную строку dir
в отдельном командном процессе, запущенном в фоновом режиме.
FOR с опцией /F
, как здесь используется, захватывает все, что написано для обработки 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
для восстановления предыдущей среды и прекращения выполнения пакетного файла до тех пор, пока пользователь не нажмет любую клавишу.
При успешном изменении текущего директораy пакетный файл продолжается, и с помощью команды ENDLOCAL начальный текущий каталог C:\TestFoder
снова устанавливается в качестве текущего каталога для командного процесса, выполняющего пакетный файл.
Для понимания используемых команд и того, какони работают, открывают окно командной строки, выполняют там следующие команды и полностью читают все страницы справки, отображаемые для каждой команды.
cd /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
md /?
move /?
pause /?
rd /?
set /?
setlocal /?