find -delete tidak menghapus direktori yang tidak kosong

32

Perintah

$ find ~ -name .DS_Store -ls -delete

bekerja pada Mac OS X, tetapi

$ find ~ -name __pycache__ -type d -ls -delete

tidak - direktori ditemukan tetapi tidak dihapus.

Mengapa?

PS. Saya tahu saya bisa melakukannya

$ find ~ -name __pycache__ -type d -ls -exec rm -rv {} +

pertanyaannya adalah mengapa find -delete tidak tidak bekerja.

sds
sumber

Jawaban:

36

find's -deletebendera bekerja sama dengan rmdirsaat menghapus direktori. Jika direktori tidak kosong ketika sudah mencapai itu direktori tidak dapat dihapus.

Anda harus mengosongkan direktori terlebih dahulu. Karena Anda menentukan -type d, findtidak akan melakukannya untuk Anda.

Anda dapat menyelesaikan ini dengan melakukan dua lintasan: pertama hapus semua yang ada dalam dir yang dinamai __pycache__, kemudian hapus semua dir yang bernama __pycache__:

find ~ -path '*/__pycache__/*' -delete
find ~ -type d -name '__pycache__' -empty -delete

Agak kurang terkontrol, tetapi dalam satu baris:

find ~ -path '*/__pycache__*' -delete

Ini akan menghapus apa pun di rumah Anda yang memiliki __pycache__bagian dari jalurnya.

GnP
sumber
Pada find 4.4.2, perintah terakhir itu harus find ~ -path '*/__pycache__*' -delete, atau mungkin find ~ -path '*/__pycache__/*' -o -name __pycache__ -deleteaman.
naught101
3
@ naught101, yang harus find ~ \( -path '*/__pycache__/*' -o -name __pycache__ \) -deletesebagai dan memiliki hak lebih atau .
Stéphane Chazelas
6

Ada beberapa alasan potensial untuk ini.

1) Anda menyuruhnya menghapus direktori saja ( -type d), dan direktori itu masih memiliki file di dalamnya.

2) Direktori Anda hanya berisi direktori lain, sehingga -type dakan menangani masalah konten. Namun Anda menggunakan OS-X, yang sebagian besar didasarkan pada FreeBSD, dan FreeBSD findsecara default akan memproses direktori sebelum isinya.
Namun -depthada opsi untuk mengatasi masalah ini dengan mengatakan finduntuk memproses direktori setelah isinya.

find ~ -name __pycache__ -type d -ls -delete -depth

Masalah ini tidak ada di linux karena -deleteopsi secara implisit memungkinkan -depth.

 

FreeBSD man 1 find:

 -depth  Always true; same as the non-portable -d option. Cause find to
   perform a depth-first traversal, i.e., directories are visited in
   post-order and all entries in a directory will be acted on before
   the directory itself. By default, find visits directories in
   pre-order, i.e., before their contents. Note, the default is not
   a breadth-first traversal.

GNU man 1 find:

 -depth Process each directory's contents before the directory itself. The -delete
        action also implies -depth.
Patrick
sumber
2
Yeah, tapi FreeBSD find (1) mengatakan untuk -delete, “pengolahan traversal ... Depth-first tersirat oleh pilihan ini.”, Dan GNU find (1) mengatakan, “... -delete menyiratkan mendalam , ...”, jadi seharusnya tidak diperlukan untuk menambah -depthperintah.
G-Man Mengatakan 'Reinstate Monica'
1
Dari findmanual GNU : "Untuk mencegah kebingungan, opsi global harus ditentukan pada baris perintah setelah daftar titik awal, tepat sebelum pengujian pertama, opsi posisi atau tindakan. Jika Anda menentukan opsi global di beberapa tempat lain, cari akan mengeluarkan pesan peringatan yang menjelaskan bahwa ini bisa membingungkan. " Sekarang, -deleteadalah "opsi global" setelah ~dalam perintah yang diberikan. Saya juga memperhatikan bahwa tidak ada bedanya apakah Anda menambahkan -depthatau tidak. Direktori kosong tetap tidak terhapus (tapi itu mungkin karena saya gunakan -maxdepthjuga)
David Tonhofer