hapus file terlama

9

Saya mencoba menghapus file lama dari direktori dan hanya menyisakan 3 file terbaru.

cd /home/user1/test

while [ `ls -lAR | grep ^- | wc -l` < 3 ] ; do

    rm `ls -t1 /home/user/test | tail -1`
    echo " - - - "

done

ada yang salah dengan pernyataan bersyarat.

d3vil0
sumber

Jawaban:

9

Jika Anda ingin mengulang file, jangan pernah gunakanls *. tl; dr Ada banyak situasi di mana Anda akhirnya akan menghapus file yang salah, atau bahkan semua file.

Yang mengatakan, sayangnya ini adalah hal yang rumit untuk dilakukan dengan benar di Bash. Ada jawaban yang bekerja lebih di sebuah pertanyaan duplikat saya bahkan lebih tuafind_date_sorted yang dapat Anda gunakan dengan modifikasi kecil:

counter=0
while IFS= read -r -d '' -u 9
do
    let ++counter
    if [[ counter -gt 3 ]]
    then
        path="${REPLY#* }" # Remove the modification time
        echo -e "$path" # Test
        # rm -v -- "$path" # Uncomment when you're sure it works
    fi
done 9< <(find . -mindepth 1 -type f -printf '%TY-%Tm-%TdT%TH:%TM:%TS %p\0' | sort -rz) # Find and sort by date, newest first

* Jangan tersinggung guys - Saya juga pernah menggunakan lssebelumnya. Tapi itu sebenarnya tidak aman.

Sunting: Barufind_date_sorted dengan unit test.

l0b0
sumber
Saya bagian kedua tentang tidak parsing ls. Juga skripnya rapi tapi saya pikir itu bisa dilakukan dalam satu liner, biarkan saya periksa ...
rahmu
Nah, Anda selalu dapat memadatkan kode Bash menjadi satu-liner, tetapi masalahnya adalah apakah itu akan dapat dibaca :)
l0b0
2
Jika saya tanpa ampun mencuri ide dari @ Peter.O, cobalah ((++counter>3))sebagai ujian Anda. Sangat ringkas. Adapun oneliners: Jika singkatnya perhatian membungkus kode dalam suatu fungsi, maka jangan khawatir tentang hal itu.
Sorpigal
@Sorpigal Jalan pintas yang rapi
l0b0
5

Untuk menghapus semua kecuali 3 file terbaru menggunakan zsh glob, Anda dapat menggunakan Om( huruf besar O) untuk mengurutkan file dari yang terlama ke yang terbaru dan subskrip untuk mengambil file yang Anda inginkan.

rm ./*(Om[1,-4])
#    | ||||  ` stop at the 4th to the last file (leaving out the 3 newest)
#    | |||` start with first file (oldest in this case)
#    | ||` subscript to pick one or a range of files
#    | |` look at modified time
#    | ` sort in descending order
#    ` start by looking at all files

Contoh lain:

# delete oldest file (both do the same thing)
rm ./*(Om[1])
rm ./*(om[-1])

# delete oldest two files
rm ./*(Om[1,2])

# delete everything but the oldest file
rm ./*(om[1,-2])
Mario Lopez
sumber
5

Sejauh ini, metode yang paling mudah adalah menggunakan zsh dan kualifikasi globalnya : Omuntuk mengurutkan berdasarkan usia yang lebih tua (yaitu yang terlama lebih dulu) dan [1,3]hanya mempertahankan tiga pertandingan pertama.

rm ./*(Om[1,3])

Lihat juga Bagaimana cara memfilter gumpalan di zsh untuk contoh lebih lanjut.

Dan perhatikan saran l0b0 : kode Anda akan rusak parah jika Anda memiliki nama file yang berisi karakter khusus shell.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Woa woa memegang kereta, apakah ini benar-benar solusi lengkap dalam 1 baris?
MetaGuru
2
@Ryan Itu zsh untukmu.
Gilles 'SANGAT berhenti menjadi jahat'
1

Anda dapat menggunakan fungsi berikut untuk mendapatkan file terbaru di direktori:

newest_in() 
{ 
    local newest=$1

    for f;do [[ $f -nt $newest ]] && newest="$f"; done;

    printf '%s\n' "$newest"
}

Berikan satu set file berbeda dengan mengeluarkan file terbaru setelah setiap iterasi.

Kiat: Jika Anda memegang set file awal dalam array yang disebut "$ {files [@]}", maka simpan indeks file terbaru yang ditemukan, dan unset 'files[index]'sebelum iterasi berikutnya.

Pemakaian: newest_in [set of files/directories]

Output sampel:

[rany$] newest_in ./*
foo.txt
[rany$]
Rany Albeg Wein
sumber
-1

Pertama, -Ropsi untuk rekursi, yang mungkin bukan yang Anda inginkan - yang akan mencari di semua subdirektori juga. Kedua, <operator (ketika tidak dilihat sebagai pengalihan) adalah untuk perbandingan string. Anda mungkin mau -lt. Mencoba:

while [ `ls -1A | grep ^- | wc -l` -lt 3 ]

Tetapi saya akan menggunakan temukan di sini:

while [ `find . -maxdepth 1 -type f -print | wc -l` -lt 3 ]
Arcege
sumber
Keduanya akan gagal jika satu atau lebih nama file berisi '$ \ n'.
Rany Albeg Wein
-1

Saya tahu itu dosa untuk diurai ls, tetapi bagaimana dengan ini:

find . -type f -maxdepth 1 | xargs ls -ltr | sed '1,3d' | awk '{print $9}' | xargs rm

Tes cepat dengan 5 file kosong:

$ >1
$ >2
$ >3
$ >4
$ >5
$ find . -type f -maxdepth 1 | xargs ls -lt | sed '1,3d' | awk '{print $9}' | xargs rm
$ ls -1
3
4
5
Rudolf Adamkovic
sumber
Ini akan gagal karena dua alasan - Parsing lsoutput dan menggunakan finddan xargsbersama - sama dengan cara yang salah. Jika Anda menggabungkan finddan xargssaya sarankan Anda untuk menggunakan finds -print0dan sesuai xargss -Opilihan. Baca tentang Menggunakan Temukan untuk informasi lebih lanjut tentang subjek. Anda mungkin juga ingin melihat dan membaca tentang mengapa Parsing sangat buruk.
Rany Albeg Wein
-2

Satu kalimat ini melakukan semua yang saya pikirkan:

ls -t1 /home/user/test | tail -n +4 | xargs -I{} rm -- "{}"
Salvo
sumber
ls adalah alat untuk melihat informasi file secara interaktif. Outputnya diformat untuk manusia dan akan menyebabkan bug pada skrip. Gunakan gumpalan atau temukan sebagai gantinya. Pahami mengapa: mywiki.wooledge.org/ParsingLs
Rany Albeg Wein
-2

Inilah salah satu solusinya:

rm /appserver/webapplogs/$(ls -t1 /appserver/webapplogs/|tail -1)
babak
sumber
1
@bakbak ls adalah alat untuk melihat informasi file secara interaktif. Outputnya diformat untuk manusia dan akan menyebabkan bug pada skrip. Lihat di sini untuk memahami alasannya . Secara khusus berbicara tentang jawaban Anda - yang ini akan rusak jika satu atau lebih file berisi karakter $ '\ n'. Juga, Pergantian Perintah (yaitu $ (...)) tidak memiliki tanda kutip ganda yang memunculkan subjek penting lainnya - Pemisahan Kata !
Rany Albeg Wein