Jak mogę usunąć wszystkie puste katalogi w poddrzewie? Użyłem czegoś takiego
find . -type d -exec rmdir {} 2>/dev/null \;
ale muszę uruchamiać wiele razy, aby usunąć katalogi zawierające tylko puste katalogi. Co więcej, jest dość powolny, szczególnie pod cygwinem.
Odpowiedzi:
Łącząc
find
opcje GNU i predykaty, to polecenie powinno wykonać zadanie:-type d
ogranicza się do katalogów-empty
ogranicza się do pustych-delete
usuwa każdy katalogDrzewo jest usuwane z liści bez potrzeby określania,
-depth
jak sugeruje to-delete
.źródło
-delete
już to sugeruje,-depth
więc nie trzeba tego określać ręcznie.-mindepth 1
tutaj, aby zapobiec usunięciu samego katalogu startowego, jeśli byłby pusty.!
ma specjalne znaczenie dla powłoki. Musisz uciec. Coś w stylu:\! -name 'Completed'
tuż przed-delete
powinno działać. Lub po prostu umieść plik znaczników w tym katalogu.Wymień katalogi głęboko zagnieżdżone jako pierwsze.
(Zauważ, że przekierowanie dotyczy całego
find
polecenia, a nie tylkormdir
. Przekierowanie tylko dlarmdir
spowoduje znaczne spowolnienie, ponieważ będziesz musiał wywołać powłokę pośrednią).Możesz uniknąć uruchamiania
rmdir
niepustych katalogów, przekazując-empty
predykat do znalezienia. GNU find sprawdza katalog, gdy ma zamiar uruchomić polecenie, więc katalogi, które właśnie zostały opróżnione, zostaną pobrane.Innym sposobem na przyspieszenie byłoby grupowanie
rmdir
wywołań. Oba będą prawdopodobnie zauważalnie szybsze niż oryginał, szczególnie pod Cygwinem. Nie oczekuję dużej różnicy między tymi dwoma.Która metoda jest szybsza, zależy od liczby niepustych katalogów. Nie można łączyć
-empty
z metodami grupowania wywołań, ponieważ wtedy katalogi zawierające tylko puste katalogi nie są puste, dopóki się na nie niefind
spojrzy.Inną metodą byłoby uruchomienie wielu przebiegów. To, czy jest to szybsze, zależy od wielu rzeczy, w tym od tego, czy cała hierarchia katalogów może pozostać w pamięci podręcznej dysku między
find
uruchomieniami.Alternatywnie użyj zsh. Glob kwalifikator
F
mecze niepuste katalogi, więc/^F
pasuje do pustych katalogów. Katalogów zawierających tylko puste katalogi nie można tak łatwo dopasować.(Kończy się, gdy
rmdir
otrzymuje pusty wiersz poleceń).źródło
-p
? Nie pomyślałbym, że to coś zmieni.-empty
powinno działać z tym (chociaż nie jestem pewien, ile dokładnie zyska). I bardzo, bardzo trywialnie, ponieważ prawdopodobnie nie chcesz go usuwać.
, używaj-mindepth 1
.-depth
argument, który czynirmdir -p
bezużytecznym. Zmieniłem już swój komentarz. Lata 90. były moją pierwotną próbą; nie ma w tym nic zaskakującego.rmdir
całkowicie usunąć polecenie, przynajmniej za pomocą GNU find, za pomocą tego polecenia:find . -depth -type d -empty -delete
Jeśli po prostu przyłożysz
-p
swoją kartęrmdir
, zadziała to w jednym przejściu. Nie będzie ładna ani optymalna, ale powinna mieć wszystko. To każe rmdirowi usunąć wszelkie niepuste katalogi nadrzędne tego, który usuwasz.Możesz trochę zaoszczędzić, dodając
-empty
test do znalezienia, aby nie zawracał sobie głowy niepustymi katalogami.źródło
find . -depth -type d -exec rmdir {} +
jest najprostszą i standardową odpowiedzią na to pytanie.
Inne podane tutaj odpowiedzi niestety zależą od ulepszeń specyficznych dla dostawcy, które nie istnieją we wszystkich systemach.
źródło
find . -type d -printf "%d %p\n" |\ sort -nr |\ perl -pe 's/^\d+\s//;' |\ while read dir; do \ (rmdir "$dir" > /dev/null 2>&1); \ done
Oto jak to działa:
rmdir
listę jeden po drugimźródło
Używam tych aliasów do często używanych
find
poleceń, szczególnie podczas czyszczenia miejsca na dysku za pomocą dupeguru , gdzie usunięcie duplikatów może spowodować powstanie wielu pustych katalogów.Komentarze w środku,
.bashrc
więc nie zapomnę ich później, kiedy będę musiał je poprawić.źródło
rm -r */
polecenie działało dla mnie łatwo.rm
powinien wymagać-f
wymuszonego usunięcia katalogów z plikami.rm -r
powinien usuwać tylko puste katalogi. Jestem otwarty na to, dlaczego to może być źle. Powinno to również pozostawić pliki, ponieważ przegląda*/
tylko foldery.źródło
rm
ma on przede wszystkim na celu usunięcie plików. Chociaż*/
pasuje tylko do katalogów, nie mam pojęcia, co robi na głębszych poziomach. Mogę sobie również wyobrazić, że działa tylko na niektórych systemach.