Bagaimana cara menghapus semua sub-direktori dari dalam direktori?

51

Pertanyaan ini semacam fase II untuk pertanyaan pertama yang saya posting di sini

Saya memiliki direktori yang berisi banyak sub-direktori, file .zip, dan file acak lainnya yang tidak terdapat dalam sub-direktori.

Saya ingin skrip baris perintah untuk menghapus semua sub-direktori dari dalam direktori induk, tetapi simpan semua file zip dan file longgar yang bukan milik sub-direktori. Semua sub-direktori memiliki konten, jadi saya yakin saya harus memaksa penghapusan mereka dengan perintah -f.

Jadi pada dasarnya, perintah yang terlihat di dalam direktori induk (atau direktori saat ini), menghapus semua folder dari dalamnya, tetapi menyimpan semua konten dan file lain yang bukan folder atau terkandung di dalam folder.

Saya mengerti bahwa menghapus item dari baris perintah memerlukan perhatian khusus, tetapi saya telah mengambil semua tindakan pencegahan yang diperlukan untuk membuat cadangan dari jarak jauh.

Evster
sumber

Jawaban:

62

Di BASH, Anda dapat menggunakan trailing slash (saya pikir itu harus bekerja di shell POSIX):

rm -R -- */

Perhatikan opsi --mana yang memisahkan dari argumen dan memungkinkan seseorang untuk menghapus entri yang dimulai dengan tanda hubung - jika tidak setelah ekspansi oleh shell nama entri akan ditafsirkan sebagai opsi oleh rm(yang sama berlaku untuk banyak utilitas baris perintah lainnya).

Tambahkan -fopsi jika Anda tidak ingin dimintai konfirmasi saat menghapus file yang tidak dapat ditulisi.

Perhatikan bahwa secara default, direktori tersembunyi (yang namanya dimulai .) akan dibiarkan sendiri.

Peringatan penting: perluasan */juga akan mencakup symlink yang akhirnya menyelesaikan ke file direktori jenis . Dan tergantung pada rmimplementasinya, rm -R -- thelink/hanya akan menghapus symlink, atau (di sebagian besar dari mereka) menghapus konten direktori tertaut secara rekursif tetapi tidak direktori itu sendiri maupun symlink.

Jika menggunakan zsh, pendekatan yang lebih baik adalah menggunakan kualifikasi glob untuk memilih file-file dari direktori tipe saja:

rm -R -- *(/) # or *(D/) to include hidden ones

atau:

rm -R -- *(-/)

untuk memasukkan symlink ke direktori (tetapi karena, kali ini, ekspansi tidak memiliki trailing /s, hanya symlink yang dihapus dengan semua rmimplementasi).

Dengan bash, AT&T ksh, yashatau zshAnda dapat melakukan:

set -- */
rm -R -- "${@%/}"

untuk menghapus trailing /.

peterph
sumber
Cantik! Ini bekerja dengan sempurna. Saya tidak menyadari itu sangat mudah dilakukan. Maukah Anda mengelaborasi -r vs -R dan apa yang dilakukan perintah-perintah itu? Terimakasih banyak.
Evster
-r, -R, --recursiveAdalah sinonim yang berarti "direktori menghapus dan isinya secara rekursif".
peterph
dapatkah Anda menjelaskan apa - dan * / lakukan?
amfibi
6
Anda juga bisa mengatakan rm -R ./*/- Ini juga menghindari masalah dengan nama tanda hubung.
l0b0
1
Berhati-hatilah untuk tidak mengubah urutan * dan /. rm -R - / * melakukan sesuatu yang sangat berbeda sehingga Anda mungkin tidak ingin terjadi: |
ChrisOdney
13

Selain cara wildcard, Anda juga dapat menggunakan find(setidaknya menemukan GNU) untuk melakukan ini:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 rm -R

Seperti findbaris lainnya , Anda dapat menjalankan bagian pertama ( find -mindepth 1 -maxdepth 1 -type d) untuk melihat daftar direktori yang akan dihapus.

Opsi yang lebih aman adalah melakukan sesuatu seperti ini:

find -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 mv -i -t ../to-rm
# or
mv -i -t ../to-rm */
# or
mv -i */ ../to-rm

yang mana saja akan memindahkan semua barang ../to-rmalih-alih menghapusnya. Anda dapat memverifikasi itu melakukan apa yang Anda inginkan, mereka rm -Rfdirektori itu di waktu luang Anda.

derobert
sumber
+1 untuk "Tempat Sampah CLI" to-rmdan findyang dengan baik menangani direktori yang diawali dengan titik (selain pelarian rumit lainnya). :)
peterph
Terima kasih atas tipnya. Saya suka gagasan pindah ke direktori terpisah sebelum menghapus. Saya bekerja melalui Terminal pada Mac OS X, dan saya percaya saya harus menginstal beberapa jenis paket GNU untuk menggunakan perintah -mindepth dan -maxdepth, benar?
Evster
@Evster tidak yakin apakah Mac OS X menemukan mendukungnya. Saya kira fink (apakah itu masih ada?) Dapat menginstal yang menemukannya. Atau Anda bisa menghilangkannya, dan kemudian memfilter daftar file yang dihasilkan menggunakan grep. Pasti menggunakan opsi mv pada itu, istead of rm.
derobert
4

Anda mungkin ingin membuat skrip untuk beberapa saran ini, terutama rm -R -- */, dan menyimpannya di folder / usr / local / bin Anda; atau buat aliasdi file ~ / .bashrc Anda. Karena sangat mudah untuk salah ketik perintah dan menghancurkan sistem Anda - bahkan satu huruf dan / atau urutan huruf dapat mengakibatkan konsekuensi bencana - ini akan berfungsi sebagai solusi yang agak lebih kuat daripada harus mengetikkan opsi dan argumen yang berbeda setiap kali Anda ingin menyelesaikan tugas ini.

Juga, Anda mungkin ingin memasukkan opsi -i or --interactive=onceatau -I or --interactive=alwayske skrip / perintah Anda yang akan berfungsi sebagai alat lain untuk menghindari penghapusan yang tidak diinginkan.

Lebih jauh, sesuatu seperti yang disarankan derobert adalah yang terbaik; cukup salin / rekatkan skrip ke file / terminal-editor dan sesuaikan dengan kebutuhan spesifik Anda, dan file / direktori akan dipindahkan ke satu direktori (konten yang dapat Anda periksa / verifikasi) yang bisa Anda hapus dengan mengeluarkan rm -rfperintah.

Pilihan lain adalah menggunakan aplikasi GUI, seperti manajer file Anda, dan cukup pilih semua file / folder yang berlaku yang ingin Anda hapus. Periksa halaman manual distribusi Anda jika Anda tidak memiliki izin.

Akhirnya, jika foldernya kosong - pada dasarnya nama file sederhana - Anda dapat menggunakan rmdirperintah untuk menghapusnya. Ini tidak berfungsi untuk semua yang mungkin ingin Anda hapus, tetapi akan berguna pada saat Anda ingin melakukan "pembersihan rumah". ** Anda mungkin ingin mencoba -p --ignore-fail-on-non-emptyopsi, yang akan memungkinkan Anda untuk menghapus sub-direktori tertentu serta "orang tua" kosong mereka - direktori di mana mereka berada.

ILMostro_7
sumber
Itu ide yang sangat bagus untuk membuat skrip terpisah yang bisa saya panggil untuk perintah ini. Bisakah Anda menjelaskan apa yang sebenarnya dilakukan opsi -i dan -I? Terima kasih!
Evster
-Saya opsi akan meminta Anda sekali setelah Anda menekan "Enter" untuk mengkonfirmasi bahwa Anda ingin menghapus ini (ketika ada lebih dari 3 file / folder "terpilih"); sedangkan opsi -i akan mengeluarkan prompt untuk setiap file, di mana Anda dapat dengan mudah mengonfirmasi dengan mengetuk "y" dan "Enter" - apa pun selain respons afirmatif akan menghasilkan file tertentu yang dilewati selama proses penghapusan.
ILMostro_7
1

Pertama, Anda perlu mendaftar direktori dan kemudian menghapusnya, tanpa menghambat file normal, ls -d * /, hanya mendaftar sub-direktori, dan memipangnya dengan rm menghapus direktori dan konten, menjaga file yang longgar tetap utuh.

Perintah ini harus melakukan pekerjaan,

ls -d  */ | xargs rm -rf
Ankit Marothi
sumber
1
Apa manfaatnya rm -rf -- */? printf '%s\0' */ | xargs -r0 rm -rf --akan membantu (dalam cangkang di mana printfbuiltin dan tidak ls) untuk bekerja di sekitar daftar arg kesalahan terlalu besar , tetapi ls -d */ | xargs rm -rftidak menambahkan apa pun AFAICT kecuali masalah tambahan.
Stéphane Chazelas
1
@AnthonyGeoghegan, ya misalnya jika ada direktori yang disebut " .."(spasi ..), itu akan menghapus konten direktori induk dengan beberapa lsimplementasi. Dan ini bukan hanya spasi, juga karakter kosong lainnya, baris baru, kutipan tunggal, kutipan ganda, backslash, dan nama file yang dimulai dengan -.
Stéphane Chazelas
2
@Ankit, Anda bisa mulai dengan mywiki.wooledge.org/ParsingLs
Stéphane Chazelas
1
Ketika Anda sepenuhnya memahami saran @ StéphaneChazelas tentang penggunaan printfuntuk menghasilkan daftar tempat setiap nama diakhiri oleh karakter nol sehingga dapat diproses xargsdengan -0opsi, saya sarankan Anda mengedit jawaban Anda untuk memperbaruinya dengan variasinya. Saya cukup yakin bahwa dia akan senang jika Anda menggunakan cuplikan kodenya jika Anda memahaminya dan telah belajar bagaimana melindungi terhadap perilaku yang tidak diinginkan yang disebabkan oleh nama file tertentu yang berpotensi ada.
Anthony G - keadilan untuk Monica
1
Menggunakan xargsmemang memiliki satu keunggulan dibandingkan jawaban yang diterima (berfungsi ketika ada banyak file / direktori di direktori saat ini) sehingga ada ruang untuk mengedit ini menjadi jawaban yang bermanfaat. Secara pribadi, saya menemukan menjawab pertanyaan Stack Exchange sebagai pengalaman belajar yang baik - terutama ketika saya mendapat umpan balik yang bermanfaat dari pengguna lain.
Anthony G - keadilan untuk Monica
-1

rm -rf <directory name>. Berhasil. Mengetikkan rm <directory name>hanya mengarah ke sejumlah sub pertanyaan di mana setiap sub direktori harus dihapus secara manual. Tetapi, rm -rfmembantu dalam menghapus seluruh direktori bersama dengan sub direktori sekaligus.

Riya Melvin
sumber
5
OP diminta untuk menyimpan isi direktori saat ini.
Stephen Rauch