Рекурсивно видаляйте порожні каталоги в Windows


91

У мене на машині Windows 7 каталог, який містить сотні, якщо не тисячі підкаталогів. У деяких з них є файли, в деяких немає. Я хочу видалити всі порожні каталоги.

Дивлячись на команду del і rmdir DOS, це виглядає не так, як ви можете це робити рекурсивно, не видаляючи всіх файлів. Чи є спосіб це зробити з командного рядка?


Я вражений, що на це питання немає простої відповіді.
billpg

@billpg: просто , як він міг би отримати: xcopy FROMDIR TODIR /s. Дивіться цей SO відповідь: stackoverflow.com/a/14742810
Екес

1
XCOPY видаляє каталоги?
billpg

1
Це легко зробити за допомогою ROBOCOPY. Детальну інформацію див. У моїй відповіді нижче.
Варун-Шарма

Відповіді:


111

Ви можете скористатися утилітою Remove Empty Directories .

Ви також можете використовувати цей пакетний файл з одним вкладишем (від DownloadSquad ):

for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"

(якщо використовується у пакетному файлі, замініть %dна %%d)

Це працює, тому що rdне буде видалено каталог, який містить файли.


6
PS Я пропоную вам спробувати спочатку інструмент на основі GUI, перш ніж спробувати будь-які команди командного рядка, які потенційно можуть видалити всі файли.
калібан

1
Переконайтесь, що він справді порожній. Прихований desktop.ini досі вважається файлом. те саме, що і великий палець.db. Якщо ви хочете перевірити, чи працює це, створіть тестовий каталог із порожніми та заповненими каталогами всередині нього. Це працює, я перевірив.
Калібан

1
Так. Це працює. Моя помилка.
EBGreen

8
for / f% d in ('dir / s / b') do rmdir "% d" має працювати, оскільки rmdir не може видалити не порожню папку
seanyboy

1
Подивіться на stackoverflow.com/a/34025977/694360, щоб дізнатися, як додати цю функціональність до контекстного меню.
mmj

46

Ви також можете використовувати РОБОКОПІЮ. Це дуже просто і його також можна використовувати для видалення порожніх папок всередині великої ієрархії.

ROBOCOPY folder1 folder1 /S /MOVE

Тут і джерело, і місце призначення folder1, оскільки вам потрібно видалити лише порожні папки, а не переміщувати інші файли в іншу папку. /SОпція полягає в тому, щоб пропустити копіювання (переміщення в цьому випадку) порожніх папок. Це також швидше, оскільки файли переміщуються всередині одного диска.


1
Магія. Отже, це переміщує всі непусті папки до того самого місця, в якому вони вже були (значить, нічого?), І пропускає порожні папки? Але тоді: чому пропуск їх призведе до видалення? І не вдалося б це перемістити вкладені папки folder1? Страшно, якщо не перевірено добре.
Ар'ян

3
@Arjan Я тестував це, і він працює чудово !. Щоб зрозуміти його роботу, потрібно перенести всі файли в інше місце, крім порожніх папок, а потім видалити залишені порожні папки. /MOVEспочатку копіює файли, а потім видаляє вихідний файл після копіювання. Отже, як /Sце використовується, він копіює непорожні папки до пункту призначення (та сама папка у наведеному вище випадку). Потім він видаляє порожні папки (наприклад, його думка, що порожні папки вже скопійовані). Ні, він не переміщує вкладені папки folder1, оскільки ROBOCOPY переміщує папки рекурсивно.
Varun Sharma

3
він навіть працює з контурами UNC (принаймні, на win7)! Блискуче!
Аріох

2
Це дуже елегантне рішення, не потребуючи стороннього програмного забезпечення. Дякую!
Маркус Мангельсдорф

1
Це просто зробило свою магію і справно працювало. Дякую!
CharleyDC5

15

Оскільки Cygwin поставляється з GNU find, ви можете зробити це:

find . -type d -empty -delete

Або щоб уникнути шуму, коли папки більше немає:

find . -type d -empty -execdir rmdir {} +

Тепер це також можна зробити за допомогою Windows 10 Bash.
Ho March

Для моєї установки Windows 10 це ( find . -type d -empty -delete) не вдається в командному рядку із наступною помилкою:FIND: Parameter format not correct
ImpressTheNet Web Developer

7

Безкоштовна утиліта EmptyFolderNuker робить це добре, із базової папки на ваш вибір. Він також видаляє ті каталоги, що містять лише порожні підкаталоги.


1
Пакетний однофаймовий файл не працював для мене (я отримую помилку "%% d був несподіваним в цей час"), і програма "Видалити порожні каталоги" не встановиться (на пов'язаній сторінці написано, що це не так все одно сумісний із Windows 7). Ця програма спрацювала як шарм.
Фенікс

1
Як писав user36580 нижче, "швидше за все, ви працюєте безпосередньо з командного рядка. У цьому випадку змініть подвійний %% на один%"
Lachlan McD.

1
Мені це подобається над чистою версією командного рядка, оскільки вона дозволяє переглядати видалені речі. Ви завжди можете викликати його з командного рядка, використовуючи "%~dp0\EmptyFolderNuker.exe" %cd%.
Єроен Вірт Плюймер

1
@ rob-kam URL для "EmptyFolderNuker" більше недоступний.
PeterCo

@PeterCo Дякую, виправлено зараз.
Роб Кам

0

Якщо у вас встановлений Cygwin , ви можете зробити це:

find -type d -exec rmdir {} \;

4
Не обов'язково. Це не може видалити каталоги лише з порожніми підкаталогами. Можливо, вам доведеться повернути його назад. знайти -тип d -принт0 | tac | xargs -0 rmdir
Ryan Thompson

Я ніколи раніше не знав про "так". Це справді чудово!
Ентоні Джорджіо

1
Або використовувати . Опція каже що - то робити , як змінити порядок виведення - він йде до найглибших рівнів каталогів, а потім працює свій шлях назад. find (starting-directory) -depth -type d ...-depthfind
G-Man

0

Якщо ви працюєте в emacs (роблячи цю платформу-агностиком), працює наступне:

(defun *-delete-empty-directories (root-directory)
  "Recursively delete empty directories in ROOT-DIRECTORY.

When called from dired, `dired-current-directory' is used for
ROOT-DIRECTORY."

  ;; Interface
  (interactive (list (if (eq major-mode 'dired-mode)
                         (expand-file-name (dired-current-directory))
                       (read-from-minibuffer "Root directory: "))))
  (when (or (null root-directory) (string= "" root-directory))
    (user-error "No root directory provided"))
  (when (called-interactively-p 'interactive)
    (unless (yes-or-no-p (format "Delete all non-empty directories in `%s'? "
                                 root-directory))
      (user-error "Directory `%s' has been left untouched" root-directory)))

  ;; Implementation
  (require 'f)
  (let ((entries (f-directories root-directory)))
    (while entries
      (let ((curdir (car entries)))
        (when (f-directories curdir)
          (*-delete-empty-directories curdir))
        (unless (f-entries curdir)
          (delete-directory curdir)
          (message "Directory deleted: `%s'" curdir))
        (setq entries (cdr entries)))))

... Скажіть, будь ласка, вам не доведеться вводити все це для того, щоб досягти цього в emacs.
Хашим

1
@Hashim Ідея полягає в тому, щоб ви його визначили в своєму init і потім прив'язали до ключа. Технічно я міг би це зв'язати, Dякби хотів, але оскільки у мене немає загальної потреби в цьому, все, що я маю набрати, - це M-x *ded RETі бам - зроблено. (Якби мені справді доводилося вводити це кожен раз, ви абсолютно праві, що це буде абсурдно - на щастя, це не так.)
Шон Алредред

Досить справедливо, це звучить більш правдоподібно.
Хашим

Чи M-x *ded RETмає якесь значення чи це випадково? Якщо останнє, як ви відстежуєте всі призначені вами ярлики emacs? Чи запам’ятовування запам'ятовується чи вам здається, що вам доведеться їх шукати?
Хашим

1
@Hashim *ded- це абревіатура для повної назви функції *-delete-empty-directories. Багато двигунів добудови (наприклад, плющ, той, який я використовую) розуміють такий нечіткий збіг. Щодо збереження їх запам’ятовується… Мені просто не потрібно. Функції, які я визначив, починаються з усіх, *тому я можу їх легко знайти, якщо вони не прив'язані до ключа. Інакше emacs сам скаже мені, чи існував більш швидкий спосіб виклику функції. Якщо все інше не вдається, завжди є apropos.
Шон Аллред

0

Поєднання публікацій Гарета та G-Man:

find . -depth -type d -empty -execdir rmdir {} +

Редагувати: Але це призвело до помилки безпеки через "C" у моєму варі PATH ... так замість цього:

$find . -depth -type d -empty | while read dir; do (rmdir -v $dir); done

Я не використовую xargs, оскільки, здається, він має обмеження вхідного рядка (приблизно 1024 рядків, я думаю?), Тоді як

 while read x; do (command $x); done

просто продовжує тривалий час, поки має внесок. Залиште багатослівний прапор '-v', якщо ви не хочете бачити результати та / або хочете, щоб він працював швидше.


0

Гммм ... можливо, навіть простіше рішення:

for /d /r %d in (*.*) do rd "%d"

Почніть це з папки, з якої потрібно видалити порожні папки.

/ d - буде працювати над папками, а не файлами / r - повторюватиме підкаталоги

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.