質問:ディレクトリ内の最新の3つを除くすべてのファイルをどのように削除しますか?
最新の3つのファイルを見つけるのは簡単です。
ls -t | head -3
しかし、最新の3つのファイルを除くすべてのファイルを見つける必要があります。それを行うにはどうすればよいですか?また、そのために不要なforループを作成せずに、同じ行でこれらのファイルを削除するにはどうすればよいですか?
私はこれにDebian Wheezyとbashスクリプトを使用しています。
これにより、最新の3つを除くすべてのファイルがリストされます。
ls -t | tail -n +4
これはそれらのファイルを削除します:
ls -t | tail -n +4 | xargs rm --
これはドットファイルもリストします:
ls -At | tail -n +4
とドットファイルで削除:
ls -At | tail -n +4 | xargs rm --
ただし、ファイル名に改行やスペースなどの面白い文字が含まれている場合、ls
の解析は危険な場合があります。ファイル名に変な文字が含まれていないことが確実な場合、ls
の解析は非常に安全です。1回限りのスクリプトであればなおさらです。
繰り返し使用するスクリプトを開発している場合は、ls
の出力を解析せず、ここで説明されているメソッドを使用しないでください。 http://mywiki.wooledge.org/ParsingLs
以下は少し複雑に見えますが、異常な、または故意に悪意のあるファイル名であっても、修正するのに非常に注意が必要です。残念ながら、GNUツールが必要です:
count=0
while IFS= read -r -d ' ' && IFS= read -r -d '' filename; do
(( ++count > 3 )) && printf '%s\0' "$filename"
done < <(find . -maxdepth 1 -type f -printf '%T@ %P\0' | sort -g -z) \
| xargs -0 rm -f --
これがどのように機能するかを説明する:
<mtime> <filename><NUL>
現在のディレクトリ内の各ファイル。sort -g -z
は、最初の列(時間)に基づいて行をNULで区切って、一般的な(整数ではなく浮動小数点)数値ソートを行います。read
ループの最初のwhile
は、mtimeを取り除きます(sort
の実行後は不要)。read
ループの2番目のwhile
は、ファイル名を読み取ります(NULまで実行)。xargs -0
は次に、そのファイル名をrm
を呼び出すために収集しているargvリストに追加します。ls -t | tail -n +4 | xargs -I {} rm {}
1ライナーが必要な場合
これは、cevingとanubhavaの答えの組み合わせです。どちらのソリューションもうまくいきません。アーカイブ内のファイルをバックアップするために毎日実行するスクリプトを探していたので、ls
の問題を回避したいと思いました(誰かがおかしな名前のファイルをバックアップフォルダーに保存した可能性があります)。だから私は私のニーズに合うように上記のソリューションを変更しました。 Cevingのソリューションは、3つの最新のファイルを削除します-私が必要として求められたものではありません。
私のソリューションはすべてのファイルを削除しますexcept 3つの最新のファイル。
find . -type f -printf '%T@\t%p\n' |
sort -t $'\t' -g |
head -n -3 |
cut -d $'\t' -f 2- |
xargs rm
いくつかの説明:
find
は、現在のフォルダー内のすべてのファイル(ディレクトリではない)をリストします。それらはタイムスタンプとともに出力されます。sort
は、タイムスタンプに基づいて行をソートします(一番古いものから順に)。head
は、最上行から最後の3行までを出力します。cut
はタイムスタンプを削除します。xargs
は、選択したすべてのファイルに対してrm
を実行します。
あなたが私の解決策を検証するために:
(
touch -d "6 days ago" test_6_days_old
touch -d "7 days ago" test_7_days_old
touch -d "8 days ago" test_8_days_old
touch -d "9 days ago" test_9_days_old
touch -d "10 days ago" test_10_days_old
)
これにより、現在のフォルダーにタイムスタンプの異なる5つのファイルが作成されます。最初にこのスクリプトを実行してから、古いファイルを削除するためのコードを実行します。
Zshの場合:
rm /files/to/delete/*(Om[1,-4])
dotfilesを含める場合は、括弧で囲まれた部分を(Om[1,-4]D)
に置き換えます。
これはファイル名の任意の文字で正しく動作すると思います(改行でチェックするだけです)。
説明:括弧にはグロブ修飾子が含まれています。 O
は「並べ替え、降順」を意味し、m
はmtimeを意味します(他の並べ替えキーについてはman zshexpn
を参照-大規模なマンページ、「並べ替え」を検索)。 [1,-4]
は、1から始まるインデックス1から(最後+ 1-4)までの一致のみを返します(3以外のすべてを削除する場合は-4
に注意してください)。
ls -t
は、空白や特殊なグロブ文字を含む可能性のあるファイル名には安全でないため、使用しないでください。
すべてのgnu
ベースのユーティリティを使用してこれを行うと、現在のディレクトリ内の最新の3つを除くすべてのファイルを削除できます。
find . -maxdepth 1 -type f -printf '%T@\t%p\0' |
sort -z -nrk1 |
tail -z -n +4 |
cut -z -f2- |
xargs -0 rm -f --
ls -t | tail -n +4 | xargs -I {} rm {}
マイケルバレントの答えは、
ls -t | tail -n +4 | xargs rm --
ファイルが3つ未満の場合、エラーをスローします
これは、find
ではなくls
を Schwartzian変換 とともに使用します。
find . -type f -printf '%T@\t%p\n' |
sort -t $'\t' -g |
tail -3 |
cut -d $'\t' -f 2-
find
はファイルを検索し、タイムスタンプでそれらを装飾し、表を使用して2つの値を分離します。 sort
は、入力をタブで分割し、浮動小数点数を正しくソートする一般的な数値ソートを実行します。 tail
は明白で、cut
は装飾されていないはずです。
装飾に関する一般的な問題は、入力の一部ではない適切な区切り文字であるファイル名を見つけることです。この answer はNULL文字を使用します。
Flohailによる回答の拡張として。最新の3つのフォルダー以外のすべてのフォルダーを削除する場合は、以下を使用します。
find . -maxdepth 1 -mindepth 1 -type d -printf '%T@\t%p\n' |
sort -t $'\t' -g |
head -n -3 |
cut -d $'\t' -f 2- |
xargs rm -rf
-mindepth 1
は親フォルダーを無視し、-maxdepth 1
サブフォルダ。