Rekurencyjnie usuwaj puste katalogi w systemie Windows

93

Mam katalog na moim komputerze z systemem Windows 7, który zawiera setki, jeśli nie tysiące podkatalogów. Niektóre z nich mają pliki, inne nie. Chcę usunąć wszystkie puste katalogi.

Patrząc na komendę del and rmdir DOS, nie wygląda na to, że można to zrobić rekurencyjnie bez usuwania wszystkich plików. Czy można to zrobić z wiersza polecenia?

mohlsen
źródło
Dziwi mnie, że nie ma prostej odpowiedzi na to pytanie.
billpg
@billpg: proste, jak mogłoby się: xcopy FROMDIR TODIR /s. Zobacz tę odpowiedź SO: stackoverflow.com/a/14742810
eckes
1
XCOPY usuwa katalogi?
billpg
1
Można to łatwo zrobić za pomocą ROBOCOPY. Zobacz moją odpowiedź poniżej, aby uzyskać szczegółowe informacje.
Varun Sharma

Odpowiedzi:

115

Możesz użyć narzędzia Usuń puste katalogi .

Alternatywnie możesz użyć tego pliku wsadowego z jedną linią (z DownloadSquad ):

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

(jeśli jest stosowany w środku plik wsadowy wymienić %dz %%d)

Działa to, ponieważ rdnie usunie katalogu zawierającego pliki.

kaliban
źródło
6
PS Proponuję najpierw wypróbować narzędzie oparte na graficznym interfejsie użytkownika, a następnie wypróbować dowolne polecenia wiersza polecenia, które mogą potencjalnie usunąć wszystkie pliki.
caliban
1
Upewnij się, że jest naprawdę pusty. Ukryty plik desktop.ini nadal jest uważany za plik. tak samo jak thumbs.db. Jeśli chcesz sprawdzić, czy to działa, utwórz katalog testowy z pustymi i zapełnionymi katalogami. Działa, zweryfikowałem.
caliban
1
Tak. To działa. Mój błąd.
EBGreen,
8
for / f% d in ('dir / s / b') do rmdir "% d" powinno działać, ponieważ rmdir nie może usunąć niepustego folderu
seanyboy 16.09.2009
1
Spójrz na stackoverflow.com/a/34025977/694360, aby dowiedzieć się, jak dodać tę funkcję do menu kontekstowego.
mmj
49

Możesz także użyć ROBOCOPY. Jest to bardzo proste i może być również użyte do usunięcia pustych folderów w dużej hierarchii.

ROBOCOPY folder1 folder1 /S /MOVE

Tutaj znajdują się zarówno źródło, jak i miejsce docelowe folder1, ponieważ wystarczy usunąć puste foldery zamiast przenosić inne pliki do innego folderu. /Sopcja polega na pominięciu kopiowania (przenoszenia, w powyższym przypadku) pustych folderów. Jest także szybszy, ponieważ pliki są przenoszone na ten sam dysk.

Varun Sharma
źródło
1
Magia. Czyli przenosi wszystkie niepuste foldery do tej samej lokalizacji, w której były już (a więc nic?) I pomija puste foldery? Ale potem: dlaczego pominięcie ich spowoduje usunięcie? I czy to nie przenosi zagnieżdżonych folderów folder1? Przerażające, chyba że dobrze przetestowane.
Arjan
3
@Arjan Przetestowałem to i działa idealnie !. Aby zrozumieć jego działanie, przypomina przenoszenie wszystkich plików w inne miejsce, z wyjątkiem pustych folderów, a następnie usuwanie pozostawionych pustych folderów. /MOVEnajpierw kopiuje pliki, a następnie usuwa plik źródłowy po skopiowaniu. Tak, jak /Sjest używany, kopiuje niepuste foldery do miejsca docelowego (ten sam folder w powyższym przypadku). Następnie usuwa puste foldery (na przykład myśląc, że puste foldery zostały już skopiowane). Nie, nie przenosi zagnieżdżonych folderów folder1, ponieważ ROBOCOPY przenosi foldery rekurencyjnie.
Varun Sharma,
3
działa nawet ze ścieżkami UNC (przynajmniej na win7)! Znakomity !
Arioch „The
2
Jest to bardzo eleganckie rozwiązanie bez potrzeby korzystania z oprogramowania innych firm. Dziękuję Ci!
Marcus Mangelsdorf,
1
To właśnie zrobiło swoją magię i działało idealnie. Dzięki!
CharleyDC5
15

Ponieważ Cygwin zawiera GNU find, możesz to zrobić:

find . -type d -empty -delete

Lub, aby uniknąć hałasu, gdy folder już nie istnieje:

find . -type d -empty -execdir rmdir {} +
Gafel
źródło
Można to również zrobić za pomocą Windows 10 Bash.
Marzec Ho
W przypadku mojej instalacji systemu Windows 10 to ( find . -type d -empty -delete) kończy się niepowodzeniem z wiersza polecenia z następującym błędem:FIND: Parameter format not correct
ImpressTheNet Web Developer
7

Bezpłatne narzędzie EmptyFolderNuker robi to dobrze, z wybranego folderu podstawowego. Usuwa również te katalogi zawierające tylko puste podkatalogi.

Rob Kam
źródło
1
Plik wsadowy z jednym wierszem nie działał dla mnie (pojawia się błąd „%% d był nieoczekiwany w tej chwili.”), A program Usuń puste katalogi nie chce się zainstalować (na połączonej stronie jest napisane, że nie jest i tak zgodny z Windows 7). Ten program działał jak urok.
Phoenix,
1
Jak napisał poniżej użytkownik 36580: „Prawdopodobnie uruchamiasz bezpośrednio z wiersza poleceń. W takim przypadku zmień podwójny %% na pojedynczy%”
Lachlan McD.
1
Podoba mi się to w czystej wersji wiersza poleceń, ponieważ umożliwia podgląd rzeczy, które zostaną usunięte. Zawsze możesz go wywołać z wiersza poleceń, używając "%~dp0\EmptyFolderNuker.exe" %cd%.
Jeroen Wiert Pluimers
1
@ rob-kam Adres URL „EmptyFolderNuker” nie jest już dostępny.
PeterCo
@PeterCo Dzięki, naprawiono teraz.
Rob Kam
0

Jeśli masz zainstalowany Cygwin , możesz to zrobić:

find -type d -exec rmdir {} \;
Anthony Giorgio
źródło
4
Niekoniecznie. To może nie usuwać katalogów zawierających tylko puste podkatalogi. Może być konieczne odwrócenie tego. znajdź -type d -print0 | tac | xargs -0 rmdir
Ryan Thompson
Nigdy wcześniej nie wiedziałem o „tac”. To naprawdę fajne!
Anthony Giorgio
1
Lub użyj . Ta opcja mówi o odwróceniu kolejności danych wyjściowych - najpierw przechodzi do najgłębszych poziomów katalogu, a następnie wraca do poprzedniego poziomu. find (starting-directory) -depth -type d ...-depthfind
G-Man
0

Jeśli pracujesz w emacsie (czyniąc to niezależnym od platformy), działają:

(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)))))
Sean Allred
źródło
... Proszę powiedz mi, że nie musisz wpisywać tego wszystkiego, aby osiągnąć to w emacs.
Hashim
1
@Hashim Chodzi o to, że masz to zdefiniowane w swoim init, a następnie powiązane z kluczem. Technicznie rzecz biorąc, mógłbym to związać, Dgdybym chciał, ale ponieważ nie mam wspólnej potrzeby, wszystko, co muszę M-x *ded RETnapisać, to i bam-made. (Gdybym rzeczywiście musiał to pisać za każdym razem, masz absolutną rację, że byłoby to absurdalne - na szczęście tak nie jest.)
Sean Allred
W porządku, to brzmi bardziej prawdopodobne.
Hashim
Czy M-x *ded RETma to jakieś znaczenie, czy jest losowe? Jeśli to drugie, w jaki sposób śledzisz wszystkie przypisane skróty emacs? Czy zapamiętywanie wystarcza, czy musisz je sprawdzić?
Hashim
1
@ Hashim *dedto skrót od pełnej nazwy funkcji *-delete-empty-directories. Wiele silników uzupełniających (takich jak bluszcz, z których korzystam) rozumie tego rodzaju rozmyte dopasowanie. Jeśli chodzi o zachowanie ich w pamięci… po prostu nie muszę. Wszystkie zdefiniowane przeze mnie funkcje zaczynają się od, *więc mogę je łatwo znaleźć, jeśli nie są powiązane z kluczem. W przeciwnym razie sam emacs powie mi, czy istnieje szybszy sposób wywołania tej funkcji. Jeśli wszystko inne zawiedzie, zawsze będzie apropos.
Sean Allred
0

Łączenie postów Garetha i G-Mana:

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

Edycja: Ale to spowodowało błąd bezpieczeństwa z powodu „C” w mojej zmiennej PATH var ... więc zamiast tego:

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

Nie używam xargs, ponieważ wydaje się, że ma limit linii wejściowej (około 1024 linii, jak sądzę?), Podczas gdy

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

po prostu działa tak długo, jak długo ma wkład. Pomiń szczegółową flagę „-v”, jeśli nie chcesz widzieć wyników i / lub chcesz, aby działało szybciej.

skeetastax
źródło
0

Hmmm ... może nawet prostsze rozwiązanie:

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

Rozpocznij od folderu, w którym chcesz usunąć puste foldery.

/ d - będzie działał na folderach, a nie na plikach / r - będzie rekursował podkatalogi

Daniel Mošmondor
źródło