Hapus semua kecuali file X terbaru di bash

157

Apakah ada cara sederhana, dalam lingkungan UNIX yang cukup standar dengan bash, untuk menjalankan perintah untuk menghapus semua kecuali file X terbaru dari direktori?

Untuk memberikan sedikit contoh konkret, bayangkan beberapa tugas cron menulis file (misalnya, file log atau cadangan ter-up) ke direktori setiap jam. Saya ingin cara menjalankan pekerjaan cron lain yang akan menghapus file tertua di direktori itu sampai ada kurang dari, katakanlah, 5.

Dan untuk memperjelas, hanya ada satu file yang hadir, itu tidak boleh dihapus.

Matt Sheppard
sumber

Jawaban:

117

Masalah dengan jawaban yang ada:

  • ketidakmampuan untuk menangani nama file dengan spasi yang disematkan atau baris baru.
    • dalam hal solusi yang menjalankan rmlangsung pada substitusi perintah yang tidak dikutip ( rm `...`), ada risiko tambahan globbing yang tidak diinginkan.
  • ketidakmampuan untuk membedakan antara file dan direktori (yaitu, jika direktori kebetulan berada di antara 5 item sistem file yang paling baru dimodifikasi, Anda akan secara efektif menyimpan kurang dari 5 file, dan mendaftar rmke direktori akan gagal).

Jawaban wnoise menjawab masalah-masalah ini, tetapi solusinya adalah spesifik- GNU (dan cukup rumit).

Berikut ini adalah pragmatis, solusi POSIX-compliant yang datang hanya dengan satu peringatan : tidak dapat menangani nama file dengan baris baru yang disematkan - tapi saya tidak menganggap itu masalah dunia nyata bagi kebanyakan orang.

Sebagai catatan, inilah penjelasan mengapa umumnya bukan ide yang baik untuk mengurai lsoutput: http://mywiki.wooledge.org/ParsingLs

ls -tp | grep -v '/$' | tail -n +6 | xargs -I {} rm -- {}

Di atas tidak efisien , karena xargsharus memanggil rmsekali untuk setiap nama file.
Platform Andaxargs memungkinkan Anda untuk mengatasi masalah ini:

Jika Anda memiliki GNU xargs , gunakan -d '\n', yang xargsmenganggap setiap input baris argumen yang terpisah, namun melewati banyak argumen yang sesuai pada baris perintah sekaligus :

ls -tp | grep -v '/$' | tail -n +6 | xargs -d '\n' -r rm --

-r( --no-run-if-empty) memastikan bahwa rmtidak dipanggil jika tidak ada input.

Jika Anda memiliki BSD xargs (termasuk di macOS ), Anda dapat menggunakan -0untuk menangani NULinput yang dipisahkan, setelah terlebih dahulu menerjemahkan baris baru ke NUL( 0x0) karakter., Yang juga meneruskan (biasanya) semua nama file sekaligus (juga akan bekerja dengan GNU xargs):

ls -tp | grep -v '/$' | tail -n +6 | tr '\n' '\0' | xargs -0 rm --

Penjelasan:

  • ls -tpmencetak nama-nama item filesystem yang diurutkan berdasarkan bagaimana mereka baru-baru ini dimodifikasi, dalam urutan menurun (item yang paling baru dimodifikasi terlebih dahulu) ( -t), dengan direktori dicetak dengan trailing /untuk menandainya ( -p).
  • grep -v '/$'lalu menyingkirkan direktori dari daftar yang dihasilkan, dengan menghilangkan ( -v) baris yang memiliki trailing /( /$).
    • Peringatan : Karena symlink yang menunjuk ke suatu direktori secara teknis bukan direktori itu sendiri, symlink tersebut tidak akan dikecualikan.
  • tail -n +6melompati 5 entri pertama dalam daftar, yang berlaku mengembalikan semua kecuali 5 file yang paling baru dimodifikasi, jika ada.
    Perhatikan bahwa untuk mengecualikan Nfile, N+1harus diteruskan ke tail -n +.
  • xargs -I {} rm -- {}(dan variasinya) kemudian memanggil rmsemua file ini; jika tidak ada kecocokan sama sekali, xargstidak akan melakukan apa pun.
    • xargs -I {} rm -- {}mendefinisikan placeholder {}yang mewakili setiap jalur input secara keseluruhan , sehingga rmkemudian dipanggil sekali untuk setiap jalur input, tetapi dengan nama file dengan ruang tertanam yang ditangani dengan benar.
    • --dalam semua kasus memastikan bahwa setiap nama file yang terjadi untuk memulai dengan -tidak keliru untuk pilihan oleh rm.

Sebuah variasi pada masalah asli, jika file yang cocok harus diproses secara individu atau dikumpulkan dalam array shell :

# One by one, in a shell loop (POSIX-compliant):
ls -tp | grep -v '/$' | tail -n +6 | while IFS= read -r f; do echo "$f"; done

# One by one, but using a Bash process substitution (<(...), 
# so that the variables inside the `while` loop remain in scope:
while IFS= read -r f; do echo "$f"; done < <(ls -tp | grep -v '/$' | tail -n +6)

# Collecting the matches in a Bash *array*:
IFS=$'\n' read -d '' -ra files  < <(ls -tp | grep -v '/$' | tail -n +6)
printf '%s\n' "${files[@]}" # print array elements
mklement0
sumber
2
Tentu saja lebih baik daripada kebanyakan jawaban di sini, jadi saya senang memberikan dukungan saya, bahkan karena saya menganggap mengabaikan kasus baris baru menjadi hal yang harus dilakukan hanya dengan hati-hati.
Charles Duffy
2
Jika Anda lstidak berada di direktori saat ini, maka path ke file akan berisi '/', yang berarti grep -v '/'tidak akan cocok dengan apa pun. Saya percaya grep -v '/$'Anda hanya ingin mengecualikan direktori.
waldol1
1
@ waldol1: Terima kasih; Saya telah memperbarui jawaban untuk memasukkan saran Anda, yang juga membuat grepperintah secara konsep lebih jelas. Perhatikan, bagaimanapun, bahwa masalah yang Anda jelaskan tidak akan muncul dengan jalur direktori tunggal; misalnya, ls -p /private/varmasih hanya akan mencetak nama file belaka. Hanya jika Anda melewati beberapa argumen file (biasanya melalui glob) Anda akan melihat path aktual di output; mis., ls -p /private/var/*(dan Anda juga akan melihat isi subdirektori yang cocok, kecuali jika Anda juga termasuk -d).
mklement0
108

Hapus semua kecuali 5 (atau apa pun nomor) dari file terbaru dalam direktori.

rm `ls -t | awk 'NR>5'`
Espo
sumber
2
Saya membutuhkan ini untuk hanya mempertimbangkan file arsip saya. ubah ls -tkels -td *.bz2
James T Snell
3
Saya menggunakan ini untuk direktori dengan mengubahnya ke rm -rf ls -t | awk 'NR>1'(Saya hanya menginginkan yang terbaru). Terima kasih!
lohiaguitar91
11
ls -t | awk 'NR>5' | xargs rm -f jika Anda lebih suka pipa dan Anda perlu menekan kesalahan jika tidak ada yang dihapus.
H2ONaCl
16
Ringkas dan mudah dibaca, mungkin, tetapi berbahaya untuk digunakan; jika mencoba menghapus file yang dibuat touch 'hello * world', ini akan menghapus semua yang ada di direktori saat ini .
Charles Duffy
1
Meskipun ini dijawab pada tahun 2008 itu berfungsi seperti pesona dan hanya apa yang saya butuhkan untuk hanya menghapus cadangan lama dari direktori tertentu. Luar biasa.
Rens Tillmann
86
(ls -t|head -n 5;ls)|sort|uniq -u|xargs rm

Versi ini mendukung nama dengan spasi:

(ls -t|head -n 5;ls)|sort|uniq -u|sed -e 's,.*,"&",g'|xargs rm
thelsdj
sumber
20
Perintah ini tidak akan dengan benar menangani file dengan spasi di namanya.
tylerl
5
(ls -t|head -n 5;ls)adalah grup perintah . Ini mencetak 5 file terbaru dua kali. sortmenyatukan garis identik. uniq -umenghapus duplikat, sehingga semua kecuali 5 file terbaru tetap. xargs rmmemanggil rmmasing-masing dari mereka.
Fabien
15
Ini menghapus semua file Anda jika Anda punya 5 atau kurang! Tambahkan --no-run-if-emptyke xargssebagai dalam (ls -t|head -n 5;ls)|sort|uniq -u|xargs --no-run-if-empty rmsilakan perbarui jawabannya.
Gonfi den Tschal
3
Bahkan yang "mendukung nama dengan spasi" berbahaya. Pertimbangkan nama yang berisi kutipan literal: touch 'foo " bar'akan membuang seluruh sisa perintah.
Charles Duffy
2
... lebih aman untuk digunakan xargs -d $'\n'daripada menyuntikkan kutipan ke konten Anda, meskipun NUL-membatasi aliran input (yang mengharuskan menggunakan sesuatu selain lsuntuk benar - benar - melakukannya dengan benar) adalah pilihan yang ideal.
Charles Duffy
59

Varian sederhana dari jawaban thelsdj:

ls -tr | head -n -5 | xargs --no-run-if-empty rm 

ls -tr menampilkan semua file, terlama lebih dulu (-t terbaru dulu, -r terbalik).

head -n -5 menampilkan semua kecuali 5 baris terakhir (yaitu 5 file terbaru).

xargs rm memanggil rm untuk setiap file yang dipilih.

Fabien
sumber
15
Perlu menambahkan --tidak-jalankan-jika-kosong ke xargs agar tidak gagal ketika ada kurang dari 5 file.
Tom
ls -1tr | head -n -5 | xargs rm <---------- Anda perlu menambahkan -1 ke ls atau Anda tidak akan mendapatkan daftar output untuk head bekerja dengan baik
Al Joslin
3
@AlJoslin, -1default ketika output ke pipeline, jadi tidak wajib di sini. Ini memiliki masalah yang jauh lebih besar, terkait dengan perilaku default xargssaat mem-parsing nama dengan spasi, tanda kutip, & c.
Charles Duffy
Tampaknya --no-run-if-emptytidak dikenali di shell saya. Saya menggunakan Cmder di windows.
StayFoolish
Mungkin perlu menggunakan -0opsi jika nama file dapat berisi spasi putih. Belum mengujinya. sumber
Keith
18
find . -maxdepth 1 -type f -printf '%T@ %p\0' | sort -r -z -n | awk 'BEGIN { RS="\0"; ORS="\0"; FS="" } NR > 5 { sub("^[0-9]*(.[0-9]*)? ", ""); print }' | xargs -0 rm -f

Memerlukan GNU find untuk -printf, dan GNU sort untuk -z, dan GNU awk untuk "\ 0", dan GNU xargs untuk -0, tetapi menangani file dengan baris atau spasi baru.

Wnoise
sumber
2
Jika Anda ingin menghapus direktori, cukup ubah -f menjadi -d dan tambahkan -r ke rm. Temukan . -maxdepth 1 -type d -printf '% T @% p \ 0' | sort -r -z -n | awk 'BEGIN {RS = "\ 0"; ORS = "\ 0"; FS = ""} NR> 5 {sub ("^ [0-9] * (. [0-9] *)?", ""); print} '| xargs -0 rm -rf
alex
1
Sekilas, saya terkejut dengan kompleksitas (atau, dalam hal ini, kebutuhan) dari awklogika. Apakah saya kehilangan beberapa persyaratan di dalam pertanyaan OP yang membuatnya perlu?
Charles Duffy
@Charles Duffy: Sub () menghapus timestamp, yang diurutkan. Stempel waktu yang diproduksi oleh "% T @" dapat mencakup bagian pecahan. Memisahkan ruang dengan FS memecah jalur dengan ruang tertanam. Saya kira menghapus melalui karya ruang pertama, tetapi hampir sama sulit untuk dibaca. Pemisah RS dan ORS tidak dapat diatur pada baris perintah, karena mereka adalah NUL.
Berkumandang
1
@wnoise, pendekatan saya yang biasa untuk ini adalah menyalurkan ke while read -r -d ' '; IFS= -r -d ''; do ...loop shell - pembacaan pertama berakhir pada spasi, sedangkan yang kedua berlanjut ke NUL.
Charles Duffy
@ Charles Duffy: Saya selalu curiga dengan kulit mentah, mungkin karena kekhawatiran mengutip Bizantium. Saya sekarang berpikir GNU sed -z -e 's/[^ ]* //; 1,5d'adalah yang paling jelas. (atau mungkinsed -n -z -e 's/[^ ]* //; 6,$p'
Berkedip
14

Semua jawaban ini gagal ketika ada direktori di direktori saat ini. Inilah sesuatu yang berfungsi:

find . -maxdepth 1 -type f | xargs -x ls -t | awk 'NR>5' | xargs -L1 rm

Ini:

  1. berfungsi ketika ada direktori di direktori saat ini

  2. mencoba untuk menghapus setiap file walaupun yang sebelumnya tidak dapat dihapus (karena izin, dll.)

  3. gagal aman ketika jumlah file dalam direktori saat ini berlebihan dan xargsbiasanya akan mengacaukan Anda (file-x )

  4. tidak memenuhi spasi dalam nama file (mungkin Anda menggunakan OS yang salah?)

Charles Wood
sumber
5
Apa yang terjadi jika findmengembalikan lebih banyak nama file daripada yang dapat diteruskan pada satu baris perintah ls -t? (Petunjuk: Anda mendapatkan beberapa kali menjalankan ls -t, yang masing-masing hanya diurutkan secara individual, daripada memiliki urutan pengurutan yang benar secara global; dengan demikian, jawaban ini rusak saat menjalankan dengan direktori yang cukup besar).
Charles Duffy
12
ls -tQ | tail -n+4 | xargs rm

Daftar nama file dengan waktu modifikasi, mengutip setiap nama file. Kecualikan dulu 3 (3 terbaru). Hapus yang tersisa.

Sunting setelah komentar bermanfaat dari mklement0 (terima kasih!): Dikoreksi -n + 3 argumen, dan perhatikan ini tidak akan berfungsi seperti yang diharapkan jika nama file berisi baris baru dan / atau direktori berisi subdirektori.

Menandai
sumber
The -Qpilihan tampaknya tidak ada di mesin saya.
Pierre-Adrien Buisson
4
Hmm, opsinya sudah ada di util inti GNU selama ~ 20 tahun, tetapi tidak disebutkan dalam varian BSD. Apakah Anda menggunakan mac?
Tandai
Aku memang. Tidak mengira ada perbedaan untuk jenis perintah yang sangat mendasar ini antara sistem terbaru. Terima kasih atas jawaban anda !
Pierre-Adrien Buisson
3
@ Mark: ++ untuk -Q. Ya, -Qadalah ekstensi GNU (inilah spesifikasi POSIXls ). Peringatan kecil (jarang masalah dalam praktiknya): -Qmenyandikan baris baru yang disematkan dalam nama file sebagai literal \n, yang rmtidak akan dikenali. Untuk mengecualikan 3 yang pertama , xargsargumen harus +4. Akhirnya, peringatan yang berlaku untuk sebagian besar jawaban lain juga: perintah Anda hanya akan berfungsi sebagaimana dimaksud jika tidak ada subdirektori dalam direktori saat ini.
mklement0
1
Ketika tidak ada yang dihapus, Anda memiliki xargs panggilan dengan --no-run-if-emptyopsi:ls -tQ | tail -n+4 | xargs --no-run-if-empty rm
Olivier Lecrivain
8

Mengabaikan baris baru berarti mengabaikan keamanan dan pengkodean yang baik. Wnoise punya satu-satunya jawaban yang bagus. Berikut ini adalah variasi pada miliknya yang menempatkan nama file dalam array $ x

while IFS= read -rd ''; do 
    x+=("${REPLY#* }"); 
done < <(find . -maxdepth 1 -printf '%T@ %p\0' | sort -r -z -n )
Ian Kelling
sumber
2
Saya sarankan membersihkan IFS- jika tidak, Anda akan berisiko kehilangan spasi putih dari nama file. Dapatkah lingkup itu ke perintah baca:while IFS= read -rd ''; do
Charles Duffy
1
mengapa "${REPLY#* }"?
msciwoj
4

Jika nama file tidak memiliki spasi, ini akan berfungsi:

ls -C1 -t| awk 'NR>5'|xargs rm

Jika nama file memiliki spasi, kira-kira seperti

ls -C1 -t | awk 'NR>5' | sed -e "s/^/rm '/" -e "s/$/'/" | sh

Logika dasar:

  • dapatkan daftar file dalam urutan waktu, satu kolom
  • dapatkan semua kecuali 5 pertama (n = 5 untuk contoh ini)
  • versi pertama: kirim ke rm
  • versi kedua: membuat script yang akan menghapusnya dengan benar
Mark Harrison
sumber
Jangan lupa while readtrik untuk berurusan dengan spasi: ls -C1 -t | awk 'NR>5' | while read d ; do rm -rvf "$d" ; done
pinkeen
1
@inkink, tidak cukup aman seperti yang diberikan di sana. while IFS= read -r dakan sedikit lebih baik - -rmencegah backslash literals dari dikonsumsi oleh read, dan IFS=mencegah pemangkasan otomatis spasi spasi tambahan.
Charles Duffy
4
BTW, jika seseorang khawatir tentang nama file yang bermusuhan, ini adalah pendekatan yang sangat berbahaya. Pertimbangkan file yang dibuat dengan touch $'hello \'$(rm -rf ~)\' world'; tanda kutip literal di dalam nama file akan melawan tanda kutip literal yang Anda tambahkan sed, menghasilkan kode dalam nama file yang dieksekusi.
Charles Duffy
1
(agar lebih jelas, "ini" di atas mengacu pada | shformulir, yang merupakan salah satu yang memiliki kerentanan injeksi shell).
Charles Duffy
2

Dengan zsh

Dengan asumsi Anda tidak peduli dengan direktori yang ada dan Anda tidak akan memiliki lebih dari 999 file (pilih jumlah yang lebih besar jika Anda mau, atau buat loop sementara).

[ 6 -le `ls *(.)|wc -l` ] && rm *(.om[6,999])

Dalam *(.om[6,999]), .file mean, ourutan sort up, rata-rata mberdasarkan tanggal modifikasi (dimasukkan auntuk waktu akses atau cuntuk perubahan inode), [6,999]memilih rentang file, jadi jangan pilih 5 terlebih dahulu.

Lolesque
sumber
Menarik, tetapi untuk kehidupan saya, saya tidak bisa mendapatkan kualifikasi glob sorting ( om) untuk bekerja (sorting apa pun yang saya coba tidak menunjukkan efek - baik pada OSX 10.11.2 (mencoba dengan zsh 5.0.8 dan 5.1.1) , atau di Ubuntu 14.04 (zsh 5.0.2)) - apa yang saya lewatkan ?. Adapun kisaran endpoint: tidak perlu keras-kode itu, hanya menggunakan -1untuk merujuk ke entri terakhir dan dengan demikian mencakup semua file yang tersisa: [6,-1].
mklement0
2

Saya menyadari ini adalah utas lama, tetapi mungkin seseorang akan mendapat manfaat dari ini. Perintah ini akan menemukan file di direktori saat ini:

for F in $(find . -maxdepth 1 -type f -name "*_srv_logs_*.tar.gz" -printf '%T@ %p\n' | sort -r -z -n | tail -n+5 | awk '{ print $2; }'); do rm $F; done

Ini sedikit lebih kuat daripada beberapa jawaban sebelumnya karena memungkinkan untuk membatasi domain pencarian Anda ke file yang cocok dengan ekspresi. Pertama, temukan file yang cocok dengan kondisi apa pun yang Anda inginkan. Cetak file-file itu dengan cap waktu di sebelahnya.

find . -maxdepth 1 -type f -name "*_srv_logs_*.tar.gz" -printf '%T@ %p\n'

Selanjutnya, urutkan berdasarkan stempel waktu:

sort -r -z -n

Kemudian, matikan 4 file terbaru dari daftar:

tail -n+5

Raih kolom ke-2 (nama file, bukan cap waktu):

awk '{ print $2; }'

Dan kemudian bungkus semuanya menjadi pernyataan:

for F in $(); do rm $F; done

Ini mungkin perintah yang lebih verbose, tapi saya lebih beruntung bisa menargetkan file kondisional dan menjalankan perintah yang lebih kompleks terhadap mereka.

TopherGopher
sumber
1

menemukan cmd menarik di Sed-Onliners - Hapus 3 baris terakhir - dan itu sempurna untuk cara lain menguliti kucing (oke tidak), tetapi ide:

 #!/bin/bash
 # sed cmd chng #2 to value file wish to retain

 cd /opt/depot 

 ls -1 MyMintFiles*.zip > BigList
 sed -n -e :a -e '1,2!{P;N;D;};N;ba' BigList > DeList

 for i in `cat DeList` 
 do 
 echo "Deleted $i" 
 rm -f $i  
 #echo "File(s) gonzo " 
 #read junk 
 done 
 exit 0
tim
sumber
1

Menghapus semua kecuali 10 file terbaru (paling baru)

ls -t1 | head -n $(echo $(ls -1 | wc -l) - 10 | bc) | xargs rm

Jika kurang dari 10 file tidak ada file yang dihapus dan Anda akan memiliki: kepala kesalahan: jumlah baris ilegal - 0

Untuk menghitung file dengan bash

luar biasa
sumber
1

Saya membutuhkan solusi elegan untuk busybox (router), semua xargs atau solusi array tidak berguna bagi saya - tidak ada perintah seperti itu tersedia di sana. temukan dan mtime bukanlah jawaban yang tepat karena kita berbicara tentang 10 item dan belum tentu 10 hari. Jawaban Espo adalah yang terpendek dan terbersih dan kemungkinan yang paling tidak bertentangan.

Kesalahan dengan spasi dan ketika tidak ada file yang akan dihapus keduanya diselesaikan dengan cara standar:

rm "$(ls -td *.tar | awk 'NR>7')" 2>&-

Versi yang sedikit lebih edukatif: Kita bisa melakukan semuanya jika kita menggunakan awk secara berbeda. Biasanya, saya menggunakan metode ini untuk mengirimkan (mengembalikan) variabel dari awk ke sh. Seperti yang kita baca sepanjang waktu yang tidak bisa dilakukan, saya mohon berbeda: inilah caranya.

Contoh untuk file tar. Tanpa masalah tentang spasi dalam nama file. Untuk menguji, ganti "rm" dengan "ls".

eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}')

Penjelasan:

ls -td *.tardaftar semua file tar. Diurutkan berdasarkan waktu. Untuk menerapkan ke semua file di folder saat ini, hapus bagian "d * .tar"

awk 'NR>7... melompati 7 baris pertama

print "rm \"" $0 "\"" membangun sebuah baris: rm "nama file"

eval jalankan itu

Karena kita menggunakan rm , saya tidak akan menggunakan perintah di atas dalam skrip! Penggunaan Wiser adalah:

(cd /FolderToDeleteWithin && eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}'))

Dalam hal menggunakan ls -t perintah tidak akan membahayakan contoh konyol seperti: touch 'foo " bar'dantouch 'hello * world' . Bukan berarti kami pernah membuat file dengan nama seperti itu di kehidupan nyata!

Sidenote. Jika kita ingin meneruskan variabel ke sh dengan cara ini, kita cukup memodifikasi cetakan (bentuk sederhana, tidak ada ruang yang ditoleransi):

print "VarName="$1

untuk mengatur variabel VarNameke nilai $1. Beberapa variabel dapat dibuat dalam sekali jalan. Ini VarNamemenjadi variabel sh normal dan biasanya dapat digunakan dalam skrip atau shell setelahnya. Jadi, untuk membuat variabel dengan awk dan mengembalikannya ke shell:

eval $(ls -td *.tar | awk 'NR>7 { print "VarName=\""$1"\""  }'); echo "$VarName"
Pila
sumber
0
leaveCount=5
fileCount=$(ls -1 *.log | wc -l)
tailCount=$((fileCount - leaveCount))

# avoid negative tail argument
[[ $tailCount < 0 ]] && tailCount=0

ls -t *.log | tail -$tailCount | xargs rm -f
Pavel Tankov
sumber
2
xargstanpa -0atau minimal -d $'\n'tidak dapat diandalkan; amati bagaimana ini berperilaku dengan file dengan spasi atau karakter kutipan dalam namanya.
Charles Duffy
0

Saya membuat ini menjadi skrip bash shell. Penggunaan: di keep NUM DIRmana NUM adalah jumlah file yang harus disimpan dan DIR adalah direktori untuk digosok.

#!/bin/bash
# Keep last N files by date.
# Usage: keep NUMBER DIRECTORY
echo ""
if [ $# -lt 2 ]; then
    echo "Usage: $0 NUMFILES DIR"
    echo "Keep last N newest files."
    exit 1
fi
if [ ! -e $2 ]; then
    echo "ERROR: directory '$1' does not exist"
    exit 1
fi
if [ ! -d $2 ]; then
    echo "ERROR: '$1' is not a directory"
    exit 1
fi
pushd $2 > /dev/null
ls -tp | grep -v '/' | tail -n +"$1" | xargs -I {} rm -- {}
popd > /dev/null
echo "Done. Kept $1 most recent files in $2."
ls $2|wc -l
Bulrush
sumber