en eski dosyaları kaldır


9

Eski dosyaları dizinden silmeye ve sadece 3 yeni dosya bırakmaya çalışıyorum.

cd /home/user1/test

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

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

done

koşullu ifadede bir şeyler yanlış.

Yanıtlar:


9

Dosyalar arasında döngü yapmak istiyorsanız, aslals * kullanmayın . tl; dr Yanlış dosyayı hatta tüm dosyaları silebileceğiniz birçok durum vardır.

Bununla birlikte, maalesef bu Bash'te yapmak zor bir şey. Küçük değişikliklerle kullanabileceğiniz daha da yaşlı bir soruya cevap veren bir soru var :find_date_sorted

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

* Suçsuz çocuklar - Daha lsönce de kullandım . Ama gerçekten güvenli değil.

Düzenleme: Yenifind_date_sorted ünite testleri ile.


Ls ayrıştırmama kısmı ikinci. Ayrıca senaryo düzgün ama bence tek bir
astarda

Bash kodunu her zaman bir astar olarak kompaktlaştırabilirsiniz, ancak sorun okunabilir olup olmayacağıdır :)
l0b0

2
@ Peter.O'dan acımasızca bir fikir çalabilirsem, ((++counter>3))test olarak dene . Güzel, kısa ve öz. Onelinerlere gelince: Eğer kısalık bir endişe ise kodu bir fonksiyona sarın, o zaman endişelenmeyin.
Sorpigal

@Sorpigal Düzgün kısayol
l0b0

5

Bir zsh glob kullanarak en yeni 3 dosya dışındaki tüm dosyaları silmek için Om(büyük O) ile dosyaları en eskiden en yeniye doğru sıralamak için ve bir alt betiği kullanarak istediğiniz dosyaları alabilirsiniz.

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

Diğer örnekler:

# 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])

5

Şimdiye kadar en kolay yöntem zsh ve glob elemelerini kullanmaktır : Omyaşı azaltarak (yani ilk önce en eski) sıralamak ve [1,3]sadece ilk üç maçı tutmaktır.

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

Ayrıca bakınız ben zsh içinde bir topak nasıl filtre Daha fazla örnek için.

Ve l0b0'ın tavsiyelerine dikkat edin : kabuk özel karakterleri içeren dosya adlarınız varsa kodunuz korkunç bir şekilde kırılacaktır.


Woa woa treni tut, bu gerçekten 1 hatta tam bir çözüm mü?
MetaGuru

2
@Ryan Bu senin için zsh.
Gilles 'SO- kötü olmayı bırak'

1

Bir dizindeki en yeni dosyayı almak için aşağıdaki işlevi kullanabilirsiniz:

newest_in() 
{ 
    local newest=$1

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

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

Her yinelemeden sonra en yeni dosyayı dışlayarak farklı bir dosya kümesi verin.

İpucu: İlk dosya kümesini "$ {files [@]}" adlı bir dizide tutarsanız, bulunan en yeni dosyanın dizinini ve bir unset 'files[index]'sonraki yinelemeden önce kaydedin .

Kullanımı: newest_in [set of files/directories]

Örnek çıktı:

[rany$] newest_in ./*
foo.txt
[rany$]

-1

İlk olarak, -Rseçenek, tüm alt dizinlerde de arama yapacak olan, muhtemelen istediğiniz şey olmayan özyineleme içindir. İkinci olarak, <operatör (yönlendirme olarak görülmediğinde) dize karşılaştırması içindir. Muhtemelen istiyorsun -lt. Deneyin:

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

Ama burada bul kullanacağım:

while [ `find . -maxdepth 1 -type f -print | wc -l` -lt 3 ]

Dosya adlarından biri veya daha fazlası '$ \ n' içeriyorsa her ikisi de başarısız olur.
Rany Albeg Wein

-1

Ayrıştırmanın günah olduğunu biliyorum ls, ama buna ne dersin:

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

5 boş dosyayla hızlı bir test:

$ >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

Ayrıştırma - Bu iki nedenden dolayı başarısız olur lsçıkışını kullanarak findve xargsyanlış şekilde bir araya. Eğer birleştirirseniz findve xargsseni kullanımı tavsiye findlar -print0ve buna göre xargss -Oseçenekleri. Konu hakkında daha fazla bilgi için Bul özelliğini kullanma hakkında bilgi edinin. Ayrıca bir göz atmak ve neden ls ayrıştırma çok kötü hakkında okumak isteyebilirsiniz .
Rany Albeg Wein

-2

Bu tek astar düşündüğüm her şeyi yapıyor:

ls -t1 /home/user/test | tail -n +4 | xargs -I{} rm -- "{}"

ls etkileşimli dosya bilgilerine bakmak için bir araçtır. Çıktıları insanlar için biçimlendirilmiştir ve komut dosyalarında hatalara neden olur. Globs kullanın veya onun yerine bulun. Nedenini anlayın: mywiki.wooledge.org/ParsingLs
Rany Albeg Wein

-2

İşte bir çözüm:

rm /appserver/webapplogs/$(ls -t1 /appserver/webapplogs/|tail -1)

1
@bakbak ls dosya bilgilerine etkileşimli olarak bakmak için bir araçtır. Çıktıları insanlar için biçimlendirilmiştir ve komut dosyalarında hatalara neden olur. Nedenini anlamak için buraya bakın . Özellikle cevabınızdan bahsetmişken - dosyalardan biri veya daha fazlası $ '\ n' karakteri içeriyorsa, bu kopacaktır. Ayrıca, Komuta Değiştirme (yani $ (...)), başka bir önemli konuyu ( Word Splitting !) Getiren çift tırnaktan yoksundur .
Rany Albeg Wein
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.