Saya menulis sebuah skrip yang menghapus semua kecuali dua file terakhir dalam folder:
#!/bin/bash
ls -1 --quoting-style=shell-always /path/to/some/folder \
| head -n -2 \
| xargs printf -- "'/path/to/some/folder/%s'\n" \
| xargs sudo rm -rf
Script ini akan dieksekusi sebagai tugas cron setiap hari.
Alasannya adalah sebagai berikut:
Dapatkan daftar semua file menggunakan
ls -1
(sehingga saya mendapatkan satu file per baris);Hapus dua yang terakhir dari daftar menggunakan
head -n -2
;Karena
ls
mencetak path relatif, gunakanxargs printf
hal itu untuk menambahkan path folder dan menjadikannya path absolut;Kirim mereka untuk
sudo rm -rf
menggunakanxargs
.
Setiap orang memiliki akses ke folder ini, jadi siapa pun dapat membuat dan menghapus file apa pun di folder ini.
Masalahnya adalah: sudo rm -rf
menakutkan. xargs sudo rm -rf
sangat menakutkan.
Saya ingin memastikan bahwa tidak ada yang dapat merusak folder / sistem lain dengan membuat file pintar untuk dihapus (baik secara tidak sengaja atau sengaja). Saya tidak tahu, sesuatu yang pintar seperti:
file with / spaces.txt
yang bisa menghasilkan super menakutkan sudo rm -rf /
.
EDIT: Kesalahan saya, nama file tidak bisa mengandung /
, jadi masalah khusus ini tidak akan terjadi, tetapi pertanyaan tentang apakah masih ada risiko lain.
Inilah sebabnya saya menggunakan --quoting-style=shell-always
, ini harus mencegah trik dengan file dengan spasi. Tapi sekarang saya bertanya-tanya apakah seseorang bisa lebih pintar dengan spasi dan kutipan dalam nama file, mungkin.
Apakah skrip saya aman?
Catatan: Saya perlu sudo
karena saya mengakses folder dari jarak jauh (dari drive jaringan yang dipetakan menggunakan mount
), dan saya tidak bisa membuatnya bekerja tanpa sudo.
printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm
?/
dalam nama dibuat Saya mencoba untuk mencapai ini kembali di sinils
output, ini sudah merupakan perintah yang ditulis dengan buruk, bahkan dengan mengutip.ls
juga menggunakan lokal untuk menyortir pesanan, saya pikir, jadi saya tidak melihat apa tujuanhead
menghapus 2 terakhir (kecuali Anda mencoba untuk menyingkirkan.
dan..
yang iirc tidak diizinkan sebagai argumen untukrm
tetap. Cukup gunakanfind /path/to/folder -type f delete
. Dan tidaksudo
jika Anda lari dari cron - cron sudah di level rootJawaban:
Di Linux, karakter apa pun adalah nama file yang merupakan karakter kecuali kecuali:
\0
(ASCII NUL): seperti yang digunakan untuk terminasi string dalam C/
(garis miring): seperti yang digunakan untuk pemisahan jalurJadi, pendekatan Anda pasti tidak akan berfungsi dalam banyak kasus seperti yang Anda bayangkan misalnya apakah ia menangani baris baru (
\n
) dalam nama file? ( Petunjuk: Tidak ).Beberapa catatan:
ls
; gunakan alat khusus (setidaknya ada satu untuk sebagian besar kasus penggunaan)xargs
, lihat apakah Anda bisa lolosfind ... -exec
; dalam banyak kasus, Anda akan baik-baik saja denganfind
sendirianSaya pikir ini akan membuat Anda pergi sekarang. steeldriver sudah memberikan gagasan NUL yang terpisah dalam komentar (
printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm
), gunakan ini sebagai titik awal.sumber
find
juga, terima kasih atas sarannya.ls
pendekatan parsing Anda akan gagal mis. Apakah Anda memperhitungkan baris baru dalam nama file?head -z
? Kedengarannya konyol tapi saya tidak punyaman
atauinfo
dalam linux wadah CoreOS saya ... Tidak dapat menemukan di internet juga. Saya mendapatkanhead: invalid option 'z'
head
(dilengkapi dengan GNUcoreutils
). Inilah versi online: manpages.ubuntu.com/manpages/xenial/man1/head.1.htmlxargs
memang mendukung beberapa penawaran: dengan tanda kutip tunggal, tanda kutip ganda atau backslash yang memungkinkannya untuk menerima argumen arbitrer¹, tetapi dengan sintaksis yang berbeda dari sintaks mengutip kerang-kerang Bourne-like.Implementasi GNU
ls
seperti yang ditemukan di Ubuntu tidak memiliki mode kutip yang kompatibel denganxargs
format input.Ini
ls --quoting-style=shell-always
kompatibel dengan ksh93, bash, dan zsh yang mengutip sintaks, tetapi hanya ketika outputls
diinterpretasikan oleh shell di lokal yang sama sepertils
ketika output. Juga, beberapa lokal, seperti yang menggunakan BIG5, BIG5-HKSCS, GBK atau GB18030 harus dihindari.Jadi dengan cangkang itu, Anda benar-benar dapat melakukan:
Tapi itu memiliki sedikit keunggulan dibandingkan:
Satu-satunya kasus di mana itu menjadi berguna adalah ketika Anda ingin menggunakan
-t
opsils
untuk mengurutkan file berdasarkan mtime / atime / ctime atau-S
/-V
. Namun meskipun begitu, Anda mungkin sebaiknya menggunakanzsh
:misalnya untuk mengurutkan file berdasarkan mtime (gunakan
oL
untuk-S
, dann
untuk-V
).Untuk menghapus semua kecuali dua file biasa yang dimodifikasi terakhir:
¹ masih ada beberapa batasan panjang (oleh
execve()
dan dalam beberapaxargs
implementasi non-GNU yang jauh lebih rendah dari yang sewenang-wenang), dan beberapaxargs
implementasi non-GNU akan tersedak input yang berisi urutan byte yang tidak membentuk karakter yang valid.sumber