Задача состоит в том, чтобы удалить все каталоги / папки, не содержащие файл PDF, а также не содержащие подкаталог / подпапку, содержащую файл PDF.Давайте рассмотрим пример, чтобы лучше понять задачу удаления каталога / папки.
Каталог C: \ Temp содержит следующие подпапки и файлы:
- Папка 1
- Подпапка A
- ПодпапкаB
- Подпапка C
- Файл 1.cmd
- Папка 2
- Подпапка A
- Подпапка B
- Подпапка C
- Файл 2.jpg
- Папка 3
- Подпапка A
- Подпапка B
- Файл 3.doc
- Последняя папка и конец
- Подпапка A
- Подпапка B
- Подпапка C
Папка отформатирована жирным шрифтом.A скрытая папка отформатирована жирным шрифтом и курсивом.Скрытый файл отформатирован курсивом.
Требуемые папки и файлы после запуска пакетного файла должны быть:
- Папка 1
- Папка 2
- Подпапка B
- Подпапка C
- Файл 2.jpg
- Последняя папка и конец
Этого можно достичь, выполнив следующий пакетный файл:
@echo off
goto MainCode
:ProcessFolder
for /F "delims=" %%I in ('dir "%~1" /AD /B 2^>nul') do call :ProcessFolder "%~1\%%I"
if exist "%~1\*.pdf" goto :EOF
for /F "delims=" %%I in ('dir "%~1" /AD /B 2^>nul') do goto :EOF
if /I "%~1\" == "%BatchFilePath%" goto :EOF
rd /Q /S "%~1"
goto :EOF
:MainCode
setlocal EnableExtensions DisableDelayedExpansion
set "BatchFilePath=%~dp0"
if exist "C:\Temp\" cd /D "C:\Temp" & call :ProcessFolder "C:\Temp"
endlocal
Для рекурсивного выполнения чего-либо в дереве каталогов требуется наличиеподпрограмма / функция / процедура, которая вызывает себя рекурсивно.В приведенном выше пакетном файле это ProcessFolder
.
Пожалуйста, прочитайте ответ на Куда возвращается GOTO: EOF? Команда goto :EOF
используется здесь для выхода из подпрограммы ProcessFolder
и работает только как требуется с включенными расширениями команд. FOR и CALL , как здесь используется, требуют также включенных расширений команд.
Сначала основной код пакетного файла явно включает расширения команд, требуемые для этого пакетного файла, и отключаетзадержка расширения переменной среды для правильной обработки также папок с восклицательным знаком в имени.Это среда по умолчанию в Windows, но здесь лучше явно указать эту среду, поскольку командный файл содержит команду RD с параметрами /Q /S
, которая может быть очень вредной для выполнения из-за неправильной средыили каталог.
Подпрограмма ProcessFolder
находится не в конце пакетного файла, как обычно, с goto :EOF
выше, чтобы избежать нежелательного падения командных строк подпрограммы после завершения всей задачи.По соображениям безопасности подпрограмма находится в середине пакетного файла.Поэтому, если пользователь пытается выполнить командный файл в Windows 95/98 без поддержки расширений команд, ничего плохого не происходит, потому что сначала goto MainCode
выполняется успешно, как и ожидалось, но SETLOCAL командная строка, вызывая подпрограмму ипоследний также ENDLOCAL сбой, и поэтому этот пакетный файл, предназначенный для Windows, не был удален ни в одном каталоге с cmd.exe
в качестве командного процессора Windows вместо command.com
.
Основной код также устанавливает текущий каталог в каталог для обработки.Таким образом, сам код C:\Temp
никогда не удаляется этим кодом, потому что Windows предотвращает удаление каталога, который является текущим каталогом любого запущенного процесса, или содержит файл, открытый запущенным процессом с разрешением доступа к файлу, чтобы другие процессы не могли удалитьфайл, открываемый процессом.
Далее вызывается подпрограмма ProcessFolder
с аргументом C:\Temp
для рекурсивной обработки этой папки.
Last восстанавливается исходное окружение, которое включает также исходный текущий каталогпри запуске пакетного файла, если этот каталог еще существует.
Команда for /D
обычно используется для выполнения каких-либо действий во всех подкаталогах каталога.Но это здесь невозможно, потому что FOR всегда игнорирует каталоги и файлы со скрытым набором атрибутов.По этой причине необходимо использовать команду DIR , чтобы получить список всех подкаталогов в текущем каталоге, включая каталоги со скрытым набором атрибутов.
Командная строка dir "%~1" /AD /B 2>nul
выполняется FOR в отдельном командном процессе, запущенном с cmd.exe /C
в фоновом режиме.Это одна из причин, почему этот пакетный файл работает довольно медленно.Другая причина заключается в том, что снова и снова вызывается подпрограмма, которая заставляет внутренне в cmd.exe
снова и снова сохранять и восстанавливать среду.
Пожалуйста, прочтите статью Microsoft о Использование операторов перенаправления команд дляобъяснение 2>nul
.Оператор перенаправления >
должен быть экранирован с помощью символа вставки ^
в командной строке FOR , чтобы интерпретироваться как литеральный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR , котораявыполняет встроенную командную строку dir
в отдельном командном процессе, запущенном в фоновом режиме.
Для каждого подкаталога в каталоге подпрограмма ProcessFolder
вызывает сама себя.Первый цикл FOR в подпрограмме остается, если каталог не содержит еще одного подкаталога.
Затем подпрограмма проверяет текущий каталог на наличие хотя бы одного файла *.pdf
.Используемое здесь условие IF выполняется, даже если каталог содержит только скрытый файл PDF.В этом случае подпрограмма завершается без каких-либо действий, поскольку этот каталог определенно содержит файл PDF и, следовательно, должен храниться в соответствии с требованиями задачи удаления папки.
Далее проверяется, если текущий каталог все еще содержит хотя быодин подкаталог, так как в этом случае текущий каталог также должен храниться, так как в одном из его подкаталогов содержится хотя бы один файл PDF.
Последнее подпрограмма проверяет, содержит ли текущий каталог случайно пакетный файл, так как этот каталог должен бытьтакже сохраняется для завершения обработки командного файла.
В противном случае текущий каталог удаляется со всеми файлами, не содержащими файл PDF и без подкаталогов, а также с текущим командным файлом, если Windows не препятствуетудаление каталога из-за отсутствия разрешений или нарушения прав доступа для общего доступа.
Обратите внимание, что пакетный файл не удаляет другие файлы в каталоге, который не может быть удален, поскольку это может бытьтакже видно на примере.
Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и полностью прочитайте все страницы справки, отображаемые для каждой команды.
call /?
cd /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rd /?
setlocal /?