Жодна відповідь, опублікована в 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 - ігнорування в цьому випадку підкаталогів із прихованим набором атрибутів. З цієї причини for /F
використовується наступний командний рядок в окремому командному процесі, розпочатому у фоновому режимі з %ComSpec% /c
:
dir "%PathToFolder%\*" /AD /B 2>nul
DIR виводиться в голому форматі через /B
записи в каталозі з атрибутом D
, тобто імена всіх підкаталогів у вказаному каталозі незалежно від інших атрибутів, таких як прихований атрибут без шляху. 2>nul
використовується для переадресації повідомлення про помилку, виведеного DIR у жодному каталозі, знайденому з ручки STDERR на пристрій NUL .
Оператору переадресації >
слід уникати символу caret, ^
у командному рядку FOR інтерпретувати як буквальний символ, коли інтерпретатор команд Windows обробляє цей командний рядок перед виконанням команди FOR, яка виконує вбудований dir
командний рядок в окремому розпочатому командному процесі у фоновому режимі.
FOR обробляє захоплений вихід, записаний для обробки STDOUT запущеного командного процесу, який є іменами підкаталогів без шляху і ніколи не укладається у подвійні лапки.
FOR з опцією /F
ігнорує порожні рядки, які тут не зустрічаються, оскільки DIR з опцією /B
не виводить порожні рядки.
FOR також ігнорує рядки, починаючи з крапки з комою, яка є кінцевим символом рядка за замовчуванням. Ім'я каталогу може починатися з крапки з комою. З цієї причини eol=|
використовується символ символу вертикальної смуги як символ кінця рядка, який жоден каталог чи файл не може мати у своєму імені.
FOR розділить рядок на підрядки, використовуючи пробіл та горизонтальну вкладку як роздільники, і призначить лише першому рядку з обмеженим пробілом / вкладками вказану змінну циклу I
. Ця поведінка розбиття тут не потрібна, оскільки ім'я каталогу може містити одне або більше пробілів. Тому delims=
використовується для визначення порожнього списку роздільників, щоб відключити поведінку розбиття рядків і присвоїти йому змінну циклу I
, завжди повне ім'я каталогу.
Команда FOR виконує команду RD для кожного імені каталогу без шляху, що є причиною, чому в командному рядку RD слід ще раз вказати шлях до папки, який з'єднаний з назвою підпапки.
Щоб зрозуміти використовувані команди та їх роботу, відкрийте вікно командного рядка, виконайте там наступні команди та прочитайте повністю всі довідкові сторінки, що відображаються для кожної команди.
del /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rd /?
rem /?
set /?
setlocal /?