it-swarm-tr.com

Bir alt ağaçtaki tüm boş dizinler nasıl kaldırılır?

Bir alt ağaçtaki tüm boş dizinleri nasıl kaldırabilirim? Gibi bir şey kullandım

find . -type d -exec rmdir {} 2>/dev/null \;

ancak yalnızca boş dizinler içeren dizinleri kaldırmak için birden çok kez çalıştırılması gerekiyor. Dahası, özellikle cygwin altında oldukça yavaş.

159
maaartinus

GNU find seçenekleri ve tahminler birleştirildiğinde, bu komut işi yapmalıdır:

find . -type d -empty -delete
  • -type d Dizinlerle kısıtlanıyor
  • -empty Boş olanlarla kısıtlanıyor
  • -delete Her dizini kaldırır

Ağaç, -depth Tarafından ima edildiği gibi -delete Belirtilmesine gerek kalmadan yapraklardan yürür.

Önce iç içe geçmiş dizinleri listeleyin.

find . -depth -type d -exec rmdir {} \; 2>/dev/null

(Yeniden yönlendirmenin yalnızca find için değil, rmdir komutu için geçerli olduğunu unutmayın. Yalnızca rmdir için yeniden yönlendirmeniz, çağırmanız gerektiğinden önemli bir yavaşlamaya neden olur bir ara Kabuk.)

rmdir öğesini boş olmayan dizinlerde -empty bulmak için yüklem. GNU find komutu çalıştırmak üzere olduğunda dizini test eder, böylece yeni boşaltılmış olan dizinler alınacaktır.

find . -depth -type d -empty -exec rmdir {} \;

Hızlandırmanın başka bir yolu, rmdir çağrılarını gruplandırmak olacaktır. Her ikisinin de özellikle Cygwin altında orijinalinden belirgin şekilde daha hızlı olması muhtemeldir. Bu ikisi arasında fazla bir fark beklemiyorum.

find . -depth -type d -print0 | xargs -0 rmdir 2>/dev/null
find . -depth -type d -exec rmdir {} + 2>/dev/null

Hangi yöntemin daha hızlı olduğu, boş olmayan dizinlerinizin sayısına bağlıdır. -empty çağrıları gruplandırma yöntemleri ile, çünkü o zaman sadece boş dizinler içeren dizinler find onlara baktığında boş değildir.

Başka bir yöntem birden fazla geçiş çalıştırmak olacaktır. Bunun daha hızlı olup olmayacağı, dizin hiyerarşisinin tamamının find çalıştırmaları arasındaki disk önbelleğinde kalıp kalamayacağı da dahil olmak üzere birçok şeye bağlıdır.

while [ -n "$(find . -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done

Alternatif olarak, zsh kullanın. glob niteleyicisiF boş olmayan dizinlerle eşleşir, bu nedenle /^F boş dizinlerle eşleşir. Yalnızca boş dizinler içeren dizinler bu kadar kolay eşleştirilemez.

while rmdir **/*(/N^F); do :; done

(Bu, rmdir boş bir komut satırı aldığında sona erer.)

Eğer sadece bir -prmdir üzerinde bir geçişte işe yarar. Güzel ya da optimal olmayacak, ama her şeyi almalı. Bu, rmdir'e, kaldırmakta olduğunuz boş olmayan üst dizinleri kaldırmasını söyler.

-empty testi bulmak, bu yüzden boş olmayan dizinlerle uğraşmaz.

6
mattdm

find . -depth -type d -exec rmdir {} +

bu sorunun en basit ve standart uyumlu cevabıdır.

Burada verilen diğer cevaplar maalesef tüm sistemlerde bulunmayan satıcıya özgü geliştirmelere bağlıdır.

3
schily

Bu takma adları özellikle sık kullanılan find komutları için kullanıyorum, özellikle dupegur kullanarak disk alanını temizlediğimde, burada yinelenenleri kaldırmak çok sayıda boş dizine neden olabilir.

İçindeki yorumlar .bashrc böylece Tweak gerekiyorsa onları daha sonra unutmayacağım.

# find empty directories
alias find-empty='find . -type d -empty'

# fine empty/zero sized files
alias find-zero='find . -type f -empty'

# delete all empty directories!
alias find-empty-delete='find-empty -delete'

# delete empty directories when `-delete` option is not available.
# output null character (instead of newline) as separator. used together
# with `xargs -0`, will handle filenames with spaces and special chars.
alias find-empty-delete2='find-empty -print0 | xargs -0 rmdir -p'

# alternative version using `-exec` with `+`, similar to xargs.
# {}: path of current file
# +: {} is replaced with as many pathnames as possible for each invocation.
alias find-empty-delete3='find-empty -exec rmdir -p {} +'

# for removing zero sized files, we can't de-dupe them automatically
# since they are technically all the same, so they are typically left
# beind. this removes them if needed.
alias  find-zero-delete='find-zero -delete'
alias find-zero-delete2='find-zero -print0 | xargs -0 rm'
alias find-zero-delete3='find-zero -exec rm {} +'
0
raychi

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

Şöyle çalışır:

  1. Tüm dizinleri derinlikleriyle birlikte yinelemeli olarak listeleyin
  2. Derinliklerinin azalan düzenine göre sırala
  3. Yalnızca dizin yollarını filtreleme
  4. Listede tek tek rmdir çalıştırın
0
Ashish Ranjan