Bagaimana cara saya menghapus direktori secara rekursif dengan wildcard?

52

Saya bekerja melalui SSH pada WD My Book World Edition. Pada dasarnya saya ingin memulai pada level direktori tertentu, dan secara rekursif menghapus semua sub-direktori yang cocok .Apple*. Bagaimana saya melakukannya?

Saya mencoba

rm -rf .Apple* dan rm -fR .Apple*

tidak ada direktori yang dihapus yang cocok dengan nama itu di dalam sub-direktori.

codedog
sumber

Jawaban:

73

find sangat berguna untuk melakukan tindakan secara selektif pada seluruh pohon.

find . -type f -name ".Apple*" -delete

Di sini, -type fpastikan itu adalah file, bukan direktori, dan mungkin tidak persis apa yang Anda inginkan karena juga akan melewatkan symlink, soket dan hal-hal lain. Anda dapat menggunakan ! -type d, yang secara harfiah berarti bukan direktori, tetapi Anda juga dapat menghapus karakter dan memblokir perangkat. Saya sarankan melihat -typepredikat di halaman manual find.

Untuk melakukannya secara ketat dengan wildcard, Anda memerlukan dukungan shell tingkat lanjut. Bash v4 memiliki globstaropsi , yang memungkinkan Anda mencocokkan subdirektori dengan menggunakan secara rekursif **. zshdan kshjuga mendukung pola ini. Dengan itu, Anda bisa melakukannya rm -rf **/.Apple*. Ini bukan standar POSIX, dan tidak terlalu portabel, jadi saya akan menghindari menggunakannya dalam skrip, tetapi untuk tindakan shell interaktif satu kali, tidak masalah.

Shawn J. Goff
sumber
3
Saya dapat mulai find . -type d -name .Apple*bekerja - ini mencantumkan semua folder. Namun, gagal ketika saya menambahkan -deletedi akhir. Itu hanya kembali dengan ringkasan penggunaan. Ini berjalan di BusyBox v1.1.1. Apakah itu membuat perbedaan?
codedog
1
-deletejuga bukan POSIX. **diperkenalkan zshpada awal 90-an. Sekarang (berdasarkan urutan penampilan) juga dalam ksh93, fish, bash dan tcsh.
Stéphane Chazelas
1
+1 untukrm -rf **/.Apple*
Andriy Boyko
1
@codedog, jika -deletetidak berfungsi gunakan -exec rm -f {} +sebagai gantinya.
Wildcard
1
Bisakah Anda findmenjadi verbose saat dihapus? Saya kira metode "globstar" akan melakukan ini dengan menambahkan -vsakelar.
Demis
17

Saya mengalami masalah finddengan -deletekarena perilaku yang disengaja find(yaitu menolak untuk menghapus jika path dimulai dengan ./, yang mereka lakukan dalam kasus saya) sebagaimana dinyatakan dalam halaman manualnya:

 -delete

Hapus file dan / atau direktori yang ditemukan. Selalu mengembalikan true. Ini dijalankan dari direktori kerja saat ini karena menemukan recurses ke bawah pohon. Itu tidak akan mencoba untuk menghapus nama file dengan karakter "/" di pathname-nya relatif terhadap "." untuk alasan keamanan.
Pemrosesan traversal mendalam-pertama diimplikasikan oleh opsi ini.
Symlink berikut tidak kompatibel dengan opsi ini.

Sebaliknya, saya hanya bisa melakukannya

find . -type d -name 'received_*_output' -exec rm -r {} +

Untuk kasus Anda, sepertinya mengutip glob (asterisk, *) adalah solusinya, tetapi saya ingin memberikan jawaban saya jika ada orang lain yang memiliki masalah yang sama.

CATATAN: Sebelumnya, jawaban saya adalah melakukan yang berikut, tetapi @Wildcard menunjukkan kelemahan keamanan dalam melakukan itu di komentar.

find . -type d -name 'received_*_output' | xargs rm -r
Menepuk
sumber
1
Tidak ada alasan bagus untuk menggunakannya di xargssini. -exec rm -r {} \;atau, lebih baik, -exec rm -r {} +akan berhasil juga tanpa gagal pada nama file karakter khusus. Lihat Mengapa mengulang-ulang hasil praktik buruk?
Wildcard
Senang mendengarnya. Tidak layak downvote, IMO, karena perintah masih menyelesaikan pekerjaan, tetapi optimasi kinerja dihargai.
Pat
1
Jika itu hanya optimasi kinerja saya akan setuju dengan Anda, tetapi tidak. Ini lubang keamanan. Anda tidak benar menangani file dengan spasi putih dalam nama mereka, dan nama file perusak yang berbahaya akan mengakibatkan hilangnya data. Juga lihat implikasi keamanan dari lupa mengutip variabel dalam bash / POSIX shells ; beberapa di antaranya dapat diterapkan dan setidaknya dapat memberi Anda gambaran tentang jenis masalah yang saya bicarakan.
Wildcard
Coba mkdir -p $'blah\nDocuments\n/etc\n/home\n/received__output'di direktori Anda dan kemudian jalankan perintah yang sama lagi, jika Anda tidak yakin ada potensi kehilangan data. Atau, karena pertanyaannya adalah tentang Mac OS mkdir -p $'blah\nDocuments\n/Users\n/Applications\n/received__output',. ( Peringatan: Anda AKAN menghapus semua file Anda jika Anda melakukan ini. Itu maksud saya.)
Wildcard
0

Apa yang mungkin adalah bahwa tidak ada yang salah dengan perintah rm / find Anda, tetapi pengguna yang Anda masuki sebenarnya tidak memiliki izin menghapus. Gunakan ls -luntuk membuat daftar hal-hal dengan izin mereka, dan Anda dapat mengidentifikasi siapa Anda dengan iddan groupsperintah (baik harus tersedia). Jika Anda adalah "pengguna yang salah" untuk melakukan ini, Anda perlu mengubah izin / kepemilikan file, atau beralih ke pengguna lain.

froztbyte
sumber
0

Mencoba:

shopt -s dotglob           # using Bash
printf '%s\n' ./.Apple*    # test
#rm -rf ./.Apple*    
jan
sumber
1
dotglobtidak berguna di sini. Lihat halaman ini untuk contoh tentang apa yang dotglob lakukan.
amfetamachine
-1

Perintah sederhana:

rm `find ./ -name '.Apple*'` -rf

Semoga berhasil!

KimKha
sumber
4
Ini sangat rawan kesalahan, cari memiliki kunci -exec.
Anton Barkovsky