Hapus file dan direktori dengan namanya. tidak ada berkas atau direktori seperti itu

32

Saya perlu menghapus semua data yang dikompilasi:

  • direktori yang disebut build,
  • direktori yang disebut obj,
  • *. jadi file.

Saya menulis sebuah perintah

find \( -name build -o -name obj -o -name *.so \) -exec rm -rf {} \;

yang melewati semua direktori secara rekursif dan menghapus semua yang saya butuhkan.

Mengapa saya memiliki output seperti itu di akhir? Mungkin saya harus menulis perintah yang berbeda.

find: `./3/obj': No such file or directory
find: `./3/build': No such file or directory
find: `./1/obj': No such file or directory
find: `./1/build': No such file or directory
find: `./2/obj': No such file or directory
find: `./2/build': No such file or directory
Maksim Dmitriev
sumber
pada sistem apa Anda? Anda harus selalu menggunakan findseperti ini dengan find /search_directory optionsmengabaikan direktori pencarian bukan ide yang baik
Kiwy
Menghapus otomatis seperti ini adalah ide yang buruk. Anda dapat memiliki skrip yang memberi Anda kandidat, yang kemudian harus Anda lihat untuk memastikan Anda tidak menghapus sesuatu yang penting atau perlu bagi sistem. Anda tidak eksplisit di mana Anda menjalankan ini. Jika Anda hanya melakukan ini di ruang pengguna, saya kira itu tidak bisa berbuat banyak kerusakan, tetapi Anda harus memastikan Anda tidak melakukan ini di area sistem secara tidak sengaja. Anda pasti ingin menjalankan skrip seperti pengguna.
Faheem Mitha
@ Kiwy, @ FaheemMitha, perintah hanya akan digunakan dalam directoty proyek; tidak akan membahayakan di sana.
Maksim Dmitriev
Terkait: stackoverflow.com/questions/22462124/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

54

Gunakan -prunepada direktori yang akan Anda hapus untuk memberi tahu findagar tidak repot mencari file di dalamnya:

find . \( -name build -o -name obj -o -name '*.so' \) -prune -exec rm -rf {} +

Perhatikan juga bahwa *.soperlu dikutip karena jika tidak dapat diperluas oleh shell ke daftar .sofile dalam direktori saat ini.

Setara dengan -regextipe GNU Anda adalah:

find . \( -name build -o -name obj -o -name '*?.so' \) -prune -exec rm -rf {} +

Perhatikan bahwa jika Anda akan menggunakan sintaksis khusus GNU, sebaiknya Anda gunakan -deletesebagai ganti -exec rm -rf {} +. Dengan -delete, GNU findmenyala -depthsecara otomatis. Itu tidak menjalankan perintah eksternal sehingga dengan cara itu, itu lebih efisien, dan juga lebih aman karena menghapus kondisi balapan di mana seseorang mungkin dapat membuat Anda menghapus file yang salah dengan mengubah direktori ke symlink di antara waktu findmenemukan file dan rmmenghapusnya (lihat info -f find -n 'Security Considerations for find'detailnya).

find . -regextype posix-egrep -regex '.*/((obj|build)(/.*)?|.+\.so)' -delete
Stéphane Chazelas
sumber
-deletejuga menangani hal-hal seperti spasi lebih baik
Izkata
@Izkata, tidak lebih baik dari -exec rm -rf {} +yang tidak memiliki masalah dengan itu juga.
Stéphane Chazelas
@StephaneChazelas - Saya bingung tentang {}- haruskah mereka dikutip atau tidak? Tampaknya berfungsi tanpa tanda kutip, tetapi Manual GNU Findutils menggunakan '{}'contohnya. Bisakah Anda menjelaskan?
grebneke
1
@ Grebneke, saya pikir ada posting di suatu tempat yang mengklaim kutipan mungkin diperlukan dalam versi yang sangat lama csh, tetapi saya tidak pernah bisa memverifikasi klaim itu. Mereka tidak diperlukan di shell modern yang saya tahu. Jelas tidak diperlukan oleh POSIX. The POSIX contoh tidak menggunakannya.
Stéphane Chazelas
3
Dan -deletetidak dapat digunakan dengan direktori.
St0rM
8

Saya kira alasannya adalah bahwa findmenghapus pohon direktori terlebih dahulu dan mencoba memeriksa isi direktori yang jelas bukan urutan terbaik. Anda dapat memaksa finduntuk memeriksa konten terlebih dahulu:

find . -depth ...

Anda harus mempertimbangkan -deleteuntuk menggunakan file dan -exec rmdirdirektori.

Hauke ​​Laging
sumber
0

Solusi saya.

find . -regextype posix-egrep -regex ".*/(obj|build|.+\.so)" -prune -exec rm -rf {} +

+ vs \; dalam perintah -exec

Maksim Dmitriev
sumber
Itu tidak selalu berhasil, hanya jika tidak ada batasan antara eksekusi yang terjadi di dalam direktori yang dihapus.
Gilles 'SO- stop being evil'
@Gilles, apa artinya "batas antara eksekusi"?
Maksim Dmitriev
1
-exec … {} +mengeksekusi perintah untuk beberapa file sekaligus, sebanyak yang sesuai pada baris perintah. Jika ada terlalu banyak file (atau lebih tepatnya jika panjang total path terlalu panjang), findakan mengeksekusi beberapa instance rm, dan dengan demikian dapat menghapus direktori yang dilaluinya. Kemungkinannya kecil +dibandingkan dengan ;tetapi +tidak menyelesaikan masalah.
Gilles 'SO- berhenti bersikap jahat'