Saya memiliki beberapa folder dengan \n
karakter itu nama mereka.
sebagai contoh:
$ ls
''$'\n''Test'
Thats merujuk ke folder dengan nama Tes dan baris kosong sebelum namanya.
Jadi ketika saya menjalankan beberapa skrip seperti ini, di direktori induknya:
while IFS= read -r d; do
rmdir $d
done < <(find * -type d)
Itu menunjukkan:
rmdir: failed to remove '': No such file or directory
rmdir: failed to remove 'Test': No such file or directory
Karena berjalan dua kali, sekali aktif \n
dan yang lain aktif Test
, karena nama folder memiliki dua baris.
Jadi bagaimana saya bisa mengatasi masalah ini sehingga, skrip tahu \nTest
hanya satu folder?
command-line
bash
scripts
Tara S Volpe
sumber
sumber
-print0
arahan find , dan-d
opsi baca. Lihat stackoverflow.com/a/40189667/7552find * -type d -print0 | while IFS= read -d '' file ; do rmdir $file ; done
perintah memiliki output inirmdir: failed to remove 'Test': No such file or directory
.rmdir "$file"
Jawaban:
Anda hanya memiliki satu perintah di sana, jadi cukup untuk menelepon
find
dengan-exec
flag flagrmdir
:Atau gunakan
-delete
opsi seperti padafind -type d -delete
, tetapi itu tidak akan berfungsi dengan direktori tidak kosong. Untuk itu Anda juga perlu-empty
bendera. Perhatikan juga,-delete
menyiratkan-depth
agar dapat dilewati. Dengan demikian alternatif lain yang memungkinkan yang menjadikan semuanya sebagai satu proses:Jika direktori tidak kosong, gunakan
rm -rf {} \;
. Untuk mengisolasi hanya direktori dengan\n
nama file, kami dapat menggabungkan kutipan ANSI-C bash$'...'
dengan-name
opption:POSIX-ly, kita bisa mengatasinya dengan cara ini:
Perlu disebutkan bahwa jika tujuan Anda adalah penghapusan direktori, maka
-delete
sudah cukup, namun jika Anda ingin menjalankan perintah pada direktori maka-exec
yang paling sesuai.Lihat juga
find
hasil?sumber
rm -rf
dengan hati-hati . ; P Tidakfind
punya-delete
opsi btw? Menghapus direktori kosong dan melempar kesalahan untuk yang tidak kosong sepertirmdir
- mungkin lebih murah.-delete
tidak akan menghapus direktori yang tidak kosong. Oleh karena itu, hati-hati penggunaanrm -rf
find
perintah tanpa muatan yang merusak (yaitu menghapus-delete
atau-exec whatever \;
) untuk memeriksa apakah daftar file yang terkena sebenarnya benar dan tidak mengandung hal-hal yang seharusnya tidak bisa dihapus ...find
. Gunakan-exec rmdir {} +
untuk mengelompokkan beberapa argumen ke dalam saturmdir
baris perintah. Dan BTW " tetapi itu tidak akan bekerja dengan direktori yang tidak kosong. " Juga berlakurmdir
, jadi itu sebenarnya bukan perbedaan-delete
. Ini perbedaan darirm -r
.find -type d -empty -delete
(-delete
tersirat-depth
).Anda bisa menggunakan shell shell alih-alih
find
:Shell glob
*/
cocok dengan semua folder di direktori saat ini. Konstruksi for-loop ini menangani pemisahan kata yang benar secara otomatis.Perhatikan bahwa tergantung pada opsi shell Anda, ini mungkin mengabaikan folder tersembunyi (nama dimulai dengan a.). Perilaku itu dapat diubah untuk mencocokkan semua file untuk sesi saat ini menggunakan perintah
shopt -s dotglob
.Juga jangan lupa untuk selalu mengutip variabel Anda.
sumber
find
halnyashopt -s globstar
dan menggunakan**/*/
glob sebagai gantinya.Kedua jawaban yang ditulis sejauh ini memanggil
rmdir
sekali per direktori, tetapi karenarmdir
dapat mengambil beberapa argumen saya bertanya-tanya: Apakah tidak ada cara yang lebih efisien?Seseorang bisa melakukannya
dan itu jelas merupakan cara termudah dan paling efisien, tetapi mungkin menimbulkan kesalahan dalam banyak direktori (lihat Berapa panjang maksimum argumen baris perintah di gnome-terminal? ). Jika Anda ingin pendekatan ini bekerja secara rekursif, aktifkan
globstar
opsi shell denganshopt -s globstar
dan gunakan**/*/
sebagai gantinya*/
.Dengan GNU
find
(dan jika kita tidak ingin menggunakannya-delete
), kita bisa melakukannyayang membangun baris perintah “dengan cara yang sama dengan yang
xargs
membangun baris perintahnya” (man find
). Pengganti-depth
untuk-maxdepth 1
jika Anda tidak ingin bekerja secara rekursif.Cara ketiga dan IMO yang brilian dijelaskan oleh steeldriver dalam jawaban ini :
Ini menggunakan shell builtin
printf
untuk membangun daftar argumen nol-dibatasi, daftar ini kemudian disalurkan kexargs
panggilan yangrmdir
tepat sesering yang diperlukan. Anda dapat membuatnya bekerja secara rekursif denganshopt -s globstar
dan**/*/
bukannya*/
seperti di atas.sumber
find
bersifat rekursif, tetapi loop OP tidak. Untuk meniru perilaku itu, gunakanfind -maxdepth 1 -type d -exec rmdir {} +
. (-depth
berlebihan dalam hal itu.) Trik rapiprintf
untuk ditirufind -print0
, saya belum pernah melihat itu sebelumnya.ls
danwhile
loop, saya melewatkan bahwa mereka mengarahkan dari proses substitusi denganfind
bukannya menyalurkanls
ke dalam loop dan hanya tidak menunjukkannya untuk beberapa alasan. Itufind *
benar-benar terkubur. Ya itu bersifat rekursif, dan akan gagal jika ada terlalu banyak entri direktori dalam direktori, termasuk non-direktori karena tidak digunakan*/
.find .
akan jauh lebih baik, karenafind
lebih cepatstat
daripada ekspansi global bash.