Ни один из ответов, опубликованных в 2018-06-01, за исключением единственной командной строки, опубликованной foxidrive , действительно не удалил все файлы и все папки / каталоги в %PathToFolder%
. По этой причине необходимо опубликовать еще один ответ с очень простой единой командной строкой для удаления всех файлов и подпапок папки, а также пакетный файл с более сложным решением, объясняющим, почему все остальные ответы, опубликованные в 2018-06-01 с использованием DEL и FOR с RD не удалось полностью очистить папку.
Простое решение для единой командной строки, которое, конечно же, также можно использовать в командном файле:
pushd "%PathToFolder%" 2>nul && ( rd /Q /S "%PathToFolder%" 2>nul & popd )
Эта командная строка содержит три команды, выполняемые одна за другой.
Первая команда PUSHD помещает текущий путь к каталогу в стек, а затем создает %PathToFolder%
текущий каталог для запуска процесса команды.
Это также работает для путей UNC по умолчанию, поскольку расширения команд включены по умолчанию, и в этом случае PUSHD создает временную букву диска, которая указывает на указанный сетевой ресурс, а затем изменяет текущий диск и каталог, используя вновь определенную букву диска.
PUSHD выводит следующее сообщение об ошибке для обработки STDERR, если указанный каталог вообще не существует:
Система не может найти указанный путь.
Это сообщение об ошибке подавляется путем перенаправления его 2>nul
на устройство NUL .
Следующая команда RD выполняется только в том случае, если изменение текущего каталога для текущего командного процесса на указанный каталог прошло успешно, то есть указанный каталог вообще существует.
Команда RD с параметрами /Q
и тихо/S
удаляет каталог со всеми подкаталогами, даже если указанный каталог содержит файлы или папки со скрытым атрибутом или с установленным атрибутом только для чтения. Системный атрибут никогда не препятствует удалению файла или папки.
Не удаляются:
Папки, используемые в качестве текущего каталога для любого запущенного процесса. Все дерево папок в такой папке не может быть удалено, если папка используется в качестве текущего каталога для любого запущенного процесса.
Файлы, открытые в настоящее время любым запущенным процессом с правами доступа к файлу, установленными для открытия файла, чтобы предотвратить удаление файла во время открытия работающим приложением / процессом. Такой открытый файл также предотвращает удаление всего дерева папок в открытый файл.
Файлы / папки, для которых у текущего пользователя нет необходимых (NTFS) разрешений на удаление файла / папки, что также предотвращает удаление дерева папок в этот файл / папку.
Первая причина не удалять папку используется этой командной строкой для удаления всех файлов и подпапок указанной папки, но не самой папки. Папка временно становится текущей директорией для запуска командного процесса, который предотвращает удаление самой папки. Конечно, это приводит к выводу сообщения об ошибке командой RD :
Процесс не может получить доступ к файлу, потому что он используется другим процессом.
Файл - это неправильный термин, поскольку в действительности папка используется другим процессом, текущим командным процессом, который выполнил команду RD . Ну, на самом деле папка для файловой системы специального файла с атрибутом файла каталогом , который объясняет это сообщение об ошибке. Но я не хочу углубляться в управление файловой системой.
Это сообщение об ошибке, как и все другие сообщения об ошибках, которые могут возникать по трем причинам, указанным выше, подавляется путем перенаправления его с 2>nul
дескриптора STDERR на NUL устройства .
Третья команда, POPD , выполняется независимо от значения выхода команды RD .
POPD извлекает путь каталога, выдвинутый PUSHD из стека, и изменяет текущий каталог для запуска процесса команды на этот каталог, то есть восстанавливает исходный текущий каталог. POPD удаляет временную букву диска, созданную PUSHD в случае пути к папке UNC.
Примечание: POPD может молча прекратить восстановление первоначального текущего каталога в случае, если исходный текущий каталог был подкаталогом каталога для очистки, который больше не существует. В этом особом случае %PathToFolder%
остается текущий каталог. Поэтому желательно запускать командную строку выше, а не из подкаталога %PathToFolder%
.
Еще один интересный факт:
я пробовал в командной строке также использовать UNC-путь, используя общий каталог C:\Temp
с именем общего ресурса Temp
и используя UNC-путь, \\%COMPUTERNAME%\Temp\CleanTest
назначенный переменной среды PathToFolder
в Windows 7. Если текущий каталог при запуске командной строки является подкаталогом общего локального каталога папка доступ с помощью UNC - пути, то есть C:\Temp\CleanTest\Subfolder1
, Subfolder1
удаляются с помощью РДА , а следующий POPD терпит неудачу молча делаю C:\Temp\CleanTest\Subfolder1
снова текущий каталог в результате Z:\CleanTest
оставшегося в качестве текущего каталога для процесса команды работает. Таким образом, в этом очень особом случае временная буква диска остается до тех пор, пока текущий каталог не будет изменен, например, с помощьюcd /D %SystemRoot%
в локальный каталог действительно существует. К сожалению, POPD не завершается со значением больше 0, если не удается восстановить исходный текущий каталог, что делает невозможным обнаружение этого особого состояния ошибки, используя только код выхода POPD . Однако можно предположить, что никто никогда не сталкивался с этим особенным случаем ошибки, поскольку пути UNC обычно не используются для доступа к локальным файлам и папкам.
Чтобы лучше понять используемые команды, откройте окно командной строки, выполните там следующие команды и внимательно прочитайте справку, отображаемую для каждой команды.
Одна строка с несколькими командами с использованием командного файла Windows объясняет операторов &&
и &
используется здесь.
Теперь давайте посмотрим на решение для пакетных файлов, используя команду DEL для удаления файлов в %PathToFolder%
и FOR и RD для удаления вложенных папок в %PathToFolder%
.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Clean the folder for temporary files if environment variable
rem PathToFolder is not defined already outside this batch file.
if not defined PathToFolder set "PathToFolder=%TEMP%"
rem Remove all double quotes from folder path.
set "PathToFolder=%PathToFolder:"=%"
rem Consisted the folder path only of double quotes?
if not defined PathToFolder goto EndCleanFolder
rem Remove a backslash at end of folder path.
if "%PathToFolder:~-1%" == "\" set "PathToFolder=%PathToFolder:~0,-1%"
rem Consisted folder path only of a backslash (with one or more double quotes)?
if not defined PathToFolder goto EndCleanFolder
rem Delete all files in specified folder including files with hidden
rem or read-only attribute set, except the files currently opened by
rem a running process which prevents deletion of the file while being
rem opened by the application, or on which the current user has not
rem the required permissions to delete the file.
del /A /F /Q "%PathToFolder%\*" >nul 2>nul
rem Delete all subfolders in specified folder including those with hidden
rem attribute set recursive with all files and subfolders, except folders
rem being the current directory of any running process which prevents the
rem deletion of the folder and all folders above, folders containing a file
rem opened by the application which prevents deletion of the file and the
rem entire folder structure to this file, or on which the current user has
rem not the required permissions to delete a folder or file in folder tree
rem to delete.
for /F "eol=| delims=" %%I in ('dir "%PathToFolder%\*" /AD /B 2^>nul') do rd /Q /S "%PathToFolder%\%%I" 2>nul
:EndCleanFolder
endlocal
Пакетный файл сначала гарантирует, что переменная среды PathToFolder
действительно определена с путем к папке без двойных кавычек и без обратной косой черты в конце. Обратная косая черта в конце не будет проблемой, но двойные кавычки в пути к папке могут быть проблематичными, поскольку PathToFolder
во время выполнения пакетного файла значение объединяется с другими строками.
Важны две строки:
del /A /F /Q "%PathToFolder%\*" >nul 2>nul
for /F "eol=| delims=" %%I in ('dir "%PathToFolder%\*" /AD /B 2^>nul') do rd /Q /S "%PathToFolder%\%%I" 2>nul
Команда DEL используется для удаления всех файлов в указанном каталоге.
- Опция
/A
необходима для обработки всех файлов, включая файлы со скрытым атрибутом, который DEL игнорировал бы без использования опции /A
.
- Опция
/F
необходима для принудительного удаления файлов с установленным атрибутом только для чтения.
- Опция
/Q
необходима для тихого удаления нескольких файлов, не запрашивая пользователя, действительно ли нужно удалить несколько файлов.
>nul
необходимо перенаправить вывод имен файлов, записанных для обработки STDOUT, на устройство NUL, которое нельзя удалить из-за того, что файл открыт в данный момент или у пользователя нет прав на удаление файла.
2>nul
необходимо перенаправить вывод сообщения об ошибке для каждого файла, который нельзя удалить из дескриптора STDERR, на устройство NUL .
Команды FOR и RD используются для удаления всех подкаталогов в указанном каталоге. Но for /D
не используется, поскольку FOR игнорирует в этом случае подкаталоги с установленным атрибутом hidden. По этой причине for /F
используется для запуска следующей командной строки в отдельном командном процессе, запущенном в фоновом режиме с помощью %ComSpec% /c
:
dir "%PathToFolder%\*" /AD /B 2>nul
DIR выводит в голом формате из-за /B
записей каталога с атрибутом D
, то есть имен всех подкаталогов в указанном каталоге, независимо от других атрибутов, таких как скрытый атрибут без пути. 2>nul
используется для перенаправления вывода сообщения об ошибке DIR на каталог, не найденный из дескриптора STDERR, на устройство NUL .
Оператор перенаправления >
должен быть экранирован с помощью символа вставки, ^
в командной строке FOR интерпретироваться как литеральный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR, которая выполняет встроенную dir
командную строку в отдельном запущенном командном процессе. на заднем фоне.
FOR обрабатывает захваченный вывод, записанный для обработки STDOUT запущенного командного процесса, которые являются именами подкаталогов без пути и никогда не заключаются в двойные кавычки.
Параметр FOR with /F
игнорирует пустые строки, которые здесь не встречаются, поскольку DIR с параметром /B
не выводит пустые строки.
FOR также игнорирует строки, начинающиеся с точки с запятой, которая является символом конца строки по умолчанию. Имя каталога может начинаться с точки с запятой. По этой причине eol=|
используется для определения символа вертикальной черты как символа конца строки, который ни один каталог или файл не может иметь в своем имени.
FOR разделит строку на подстроки, используя пробел и горизонтальную табуляцию в качестве разделителей, и назначит только первую строку с пробелом / табуляцией для указанной переменной цикла I
. Такое поведение разделения здесь нежелательно, поскольку имя каталога может содержать один или несколько пробелов. Поэтому delims=
используется для определения пустого списка разделителей, чтобы отключить поведение разделения строк и получить присвоение переменной цикла I
, всегда полное имя каталога.
Команда FOR запускает команду RD для каждого имени каталога без пути, поэтому в командной строке RD необходимо еще раз указать путь к папке, который объединяется с именем подпапки.
Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и внимательно прочитайте все страницы справки, отображаемые для каждой команды.
del /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rd /?
rem /?
set /?
setlocal /?