Мне удалось создать макрос, который на самом деле может удалять пустые файлы и пустые папки в иерархии папок.
Я потратил некоторое время, чтобы разобраться с этим, но теперь онработает:
@ECHO OFF
SET topLevel=%cd%
FOR /D /R %%D IN (*) DO (
CD %%D
FOR %%F IN (*) DO IF %%~zF EQU 0 DEL "%%F"
)
CD %topLevel%
FOR /F "usebackq delims=" %%D IN (`"DIR/AD/B/S|SORT/R"`) DO RD "%%D"
Сначала отключает эхо (удалите @ECHO OFF, если вы хотите прочитать, что на самом деле происходит).Затем он сохраняет текущую папку в переменной topLevel.Далее необходимо пройти через все папки «% D» с помощью команды FOR в текущей папке и всех подпапок.Он меняет локальный каталог на каждую из найденных подпапок (CD %% D).В каждой подпапке, используя другой цикл FOR, он находит и удаляет все файлы %% F, для которых размер файла (~ z для %% ~ zF) равен 0. Когда весь этот двойной цикл завершен, все пустые файлы фактически удаляются с диска.Теперь создается новая команда FOR для выполнения RD %% D для удаления каждого каталога.Из-за безопасности DOS здесь будут удалены только пустые папки.Папки с файлами внутри остаются без изменений.
Но, эй, кто сказал, что вы не можете улучшить еще раз?
Я еще раз переработал скрипт, теперь сильно оптимизирован для быстрая обработка :
@ECHO OFF
SET topLevel=%CD%
FOR /D /R %%D IN (*) DO (
CD %%D
CALL :innerLoop
)
CD %topLevel%
FOR /F "usebackq delims=" %%D IN (`"DIR /AD/B/S | SORT /R"`) DO RD "%%D"
GOTO :break
:innerLoop
FOR /F "delims=" %%F IN ('DIR/B/A-D/OS') DO IF %%~zF EQU 0 (DEL "%%F") ELSE (GOTO :break)
:break
Проблема с предыдущим состояла в том, что два вложенных цикла FOR касались каждого отдельного файла.Поскольку пустые файлы встречаются редко, абсолютно не нужно трогать каждый файл, и это большая трата времени.Я попытался запустить его на томе объемом 25 ТБайт с ~ 5 миллионами файлов ..
Поэтому я изменил внутренний цикл для сортировки файлов по размеру в команде DIR с помощью параметра / OS (Упорядоченный размер).Параметр / AD не выводит список каталогов, поэтому остаются только истинные файлы (каталоги также указаны как размер 0, поэтому я добавил это).Для каждого файла проверяется размер.Как только найден файл размером более 0 байт, цикл завершается с помощью GOTO: break.Так как файлы отсортированы по размеру, сначала наименьший, его можно безопасно выполнять следующим образом.Огромная экономия времени!
Поскольку команда DOS FOR не имеет элегантного способа выйти из цикла, я использовал эту странную конструкцию для вызова внутреннего цикла с помощью GOTO: break.
Кажется, он работает около в несколько тысяч раз быстрее на моем большом томе, чем предыдущий; -)
Надеюсь, вам понравится!
С уважением, Аксель Мертес
PS: Самый большой кошмар в сценариях DOS - это понимание, когда вам нужен %% или%, 'или "и т. Д.