it-swarm-id.com

Bagaimana cara menghapus semua direktori kosong di subtree?

Bagaimana saya bisa menghapus semua direktori kosong di subtree? Saya menggunakan sesuatu seperti

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

tapi saya perlu dijalankan beberapa kali untuk menghapus direktori yang berisi direktori kosong saja. Selain itu, ini sangat lambat, terutama di bawah cygwin.

159
maaartinus

Menggabungkan GNU find pilihan dan predikat, perintah ini harus melakukan pekerjaan:

find . -type d -empty -delete
  • -type d membatasi direktori
  • -empty membatasi ke yang kosong
  • -delete menghapus setiap direktori

Pohon itu berjalan dari daun tanpa perlu menyebutkan -depth seperti yang tersirat oleh -delete.

Daftar direktori bersarang-pertama.

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

(Perhatikan bahwa pengalihan berlaku untuk perintah find secara keseluruhan, bukan hanya untuk rmdir. Mengarahkan hanya untuk rmdir akan menyebabkan pelambatan yang signifikan karena Anda harus memohon Shell menengah.)

Anda dapat menghindari menjalankan rmdir pada direktori yang tidak kosong dengan melewatkan -empty predikat untuk ditemukan. GNU find menguji direktori ketika hendak menjalankan perintah, sehingga direktori yang baru saja dikosongkan akan diambil.

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

Cara lain untuk mempercepat adalah mengelompokkan doa rmdir. Keduanya cenderung lebih cepat dari aslinya, terutama di bawah Cygwin. Saya tidak berharap banyak perbedaan antara keduanya.

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

Metode mana yang lebih cepat tergantung pada berapa banyak direktori kosong yang Anda miliki. Anda tidak dapat menggabungkan -empty dengan metode untuk mengelompokkan doa, karena direktori yang hanya berisi direktori kosong tidak kosong pada saat find melihatnya.

Metode lain adalah dengan menjalankan beberapa lintasan. Apakah ini lebih cepat tergantung pada banyak hal, termasuk apakah seluruh hierarki direktori dapat tetap berada dalam cache disk antara find berjalan.

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

Atau, gunakan zsh. Kualifikasi glob F cocok dengan direktori yang tidak kosong, jadi /^F cocok dengan direktori kosong. Direktori yang hanya berisi direktori kosong tidak dapat dicocokkan dengan mudah.

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

(Ini berakhir ketika rmdir menerima baris perintah kosong.)

Jika Anda hanya memasang -p pada rmdir Anda, itu akan bekerja dalam satu pass. Tidak akan cantik atau optimal, tetapi harus mendapatkan segalanya. Itu memberitahu rmdir untuk menghapus direktori induk yang tidak kosong dari direktori yang Anda hapus.

Anda dapat menyimpan sedikit dengan menambahkan -empty tes untuk menemukan, sehingga tidak mengganggu dengan direktori yang tidak kosong.

6
mattdm

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

adalah jawaban yang paling sederhana dan sesuai standar untuk pertanyaan ini.

Sayangnya, jawaban lain yang diberikan di sini bergantung pada perangkat tambahan khusus vendor yang tidak ada pada semua sistem.

3
schily

Saya menggunakan alias ini untuk perintah find yang sering digunakan, terutama ketika saya membersihkan ruang disk menggunakan dupegur, di mana menghapus duplikat dapat menghasilkan banyak direktori kosong.

Komentar di dalam .bashrc jadi saya tidak akan melupakannya nanti ketika saya perlu men-tweak itu.

# 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

Begini cara kerjanya:

  1. Secara rekursif daftarkan semua direktori beserta kedalamannya
  2. Urutkan berdasarkan urutan kedalamannya
  3. Memfilter hanya jalur direktori
  4. Jalankan rmdir pada daftar satu per satu
0
Ashish Ranjan