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.
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 direktoriPohon 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.
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.
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 {} +'
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:
rmdir
pada daftar satu per satu