最も古いファイルを削除する


9

ディレクトリから古いファイルを削除して、最新のファイルを3つだけ残そうとしています。

cd /home/user1/test

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

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

done

条件文に問題があります。

回答:


9

ファイルをループする場合は、*を使用しないでくださいls。tl; dr間違ったファイルやすべてのファイルを削除してしまう状況がたくさんあります。

とは言っても、残念ながらこれはBashで正しく行うにはトリッキーなことです。時を超える作業の答えがあります重複した質問は、私も、古いあなたは小さな変更で使用することができました。 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

*違反者はいません- ls以前も使用しました。しかし、それは本当に安全ではありません。

編集:単体テストの新機能find_date_sorted


私はlsを解析しないことについて次の部分に行きます。また、スクリプトはきちんとしていますが、1つのライナーで実行できると思います。確認させてください...
rahmu

ええと、いつでもBashコードを1行に圧縮できますが、問題はそれが読み取り可能かどうかです:)
l0b0

2
私が容赦なく@ Peter.Oからアイデアを盗む可能性がある場合は((++counter>3))、テストとして試してください。それはうまく簡潔です。ワンライナーに関して:簡潔さを気にする場合は、コードを関数でラップすることで心配する必要はありません。
Sorpigal 2012

@Sorpigal Neatショートカット
l0b0

5

zsh globを使用して最新の3つのファイルを除くすべてを削除するには、Om(大文字のO)を使用してファイルを古いものから新しいものに並べ替え、添え字を使用して必要なファイルを取得します。

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

その他の例:

# 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

これまでで最も簡単な方法は、そのzshの使用することですグロブ修飾子Omソートに年齢を減少させることによって(すなわち古い順)と[1,3]のみ最初の3つの試合を保持します。

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

その他の例については、zshグロブをフィルタリングする方法も参照してください。

l0b0のアドバイスに注意してください。シェルの特殊文字を含むファイル名があると、コードがひどく壊れてしまいます。


Woa woaが列車を停めます。これは本当に1行で完全なソリューションですか?
MetaGuru

2
@ライアンそれはあなたのためのzshです。
Gilles「SO-邪悪なことをやめなさい」

1

次の関数を使用して、ディレクトリ内の最新のファイルを取得できます。

newest_in() 
{ 
    local newest=$1

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

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

各反復後に最新のファイルを除外することにより、異なるファイルセットを提供します。

ヒント:「$ {files [@]}」と呼ばれる配列にファイルの初期セットを保持している場合は、見つかった最新のファイルのインデックスをunset 'files[index]'次の反復の前に保存します。

使用法: newest_in [set of files/directories]

出力例:

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

-1

まず、-Rオプションは再帰ですが、これはおそらく望んでいるものではありません。すべてのサブディレクトリも検索されます。次に、<演算子(リダイレクトとして表示されない場合)は文字列比較用です。あなたはおそらく望み-ltます。試してください:

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

しかし、私はここでfindを使用します:

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

1つ以上のファイル名に「$ \ n」が含まれている場合、どちらも失敗します。
Rany Albeg Wein 2013

-1

私はそれが解析する罪であることを知っていますls、しかしこれはどうですか:

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

5つの空のファイルを使用した簡単なテスト:

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

解析-この1は、2つの理由のために失敗しlsた出力をし、使用findし、xargs間違った方法で一緒に。あなたが結合した場合findxargs、私は使用することをお勧めいたしますfind-print0それに応じてxargs-Oオプション。件名の詳細については、「検索の使用」をお読みください。また、lsの解析が非常に悪い理由を調べて読むこともできます。
Rany Albeg Wein 2013

-2

このワンライナーは私が思うすべてのことを行います:

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

lsはファイル情報をインタラクティブに見るためのツールです。その出力は人間用にフォーマットされており、スクリプトにバグを引き起こします。代わりに、globsまたはfindを使用してください。理由を理解する:mywiki.wooledge.org/ParsingLs
Rany Albeg Wein

-2

これが1つの解決策です。

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

1
@bakbak lsは、ファイル情報をインタラクティブに表示するためのツールです。その出力は人間用にフォーマットされており、スクリプトにバグを引き起こします。ここを見て理由を理解してください。具体的にはあなたの答えについて話す-1つ以上のファイルに$ '\ n'文字が含まれている場合、これは壊れます。また、コマンド置換(つまり$(...))には二重引用符がなく、別の重要な主題である単語分割が生じます。
Rany Albeg Wein 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.