ディレクトリをログファイルでいっぱいに管理しやすくしようとしています。毎晩、最新の10個を除くすべてを削除します。単一のコマンドでこれを行うにはどうすればよいですか?
ディレクトリをログファイルでいっぱいに管理しやすくしようとしています。毎晩、最新の10個を除くすべてを削除します。単一のコマンドでこれを行うにはどうすればよいですか?
回答:
ポータブルで信頼できるソリューションについては、これを試してください:
ls -1tr | head -n -10 | xargs -d '\n' rm -f --
tail -n -10
他の回答のいずれかの構文はどこでも機能しないようです(つまり、RHEL5システムでは機能しません)。
また、コマンドラインで$()
または``
を使用してrm
、
xargs
文字制限内で渡すことができる引数の数を自動的に把握し-d '\n'
、入力の行境界でのみ分割するため、これらの問題の両方を修正します。技術的には、改行を含むファイル名で問題が発生する可能性がありますが、それはスペースを含むファイル名よりもはるかに一般的ではなく、改行を回避する唯一の方法ははるかに複雑で、おそらくperlではないにしても少なくともawkが関与します。
xargs(古いAIXシステム、おそらく?)がない場合は、ループにすることができます。
ls -1tr | head -n -10 | while IFS= read -r f; do
rm -f "$f"
done
rm
ファイルごとに個別に生成されるため、これは少し遅くなりますが、上記の警告1と2を回避します(ただし、ファイル名に改行が含まれています)。
head(1)
manページから:-n, --lines=[-]K print the first K lines instead of the first 10; with the leading '-', print all but the last K lines of each file
head
とxargs
ギブ・エラー。正しい選択肢があるhead -n 10
とxargs rm -f
。完全なコマンドがあるls -1tr ./ | head -n 10 | xargs rm -rf
ls -1tr
は、文字「L」ではなく、数字ONEであることに注意してください。
スクリプトに含めるコードは
rm -f $(ls -1t /path/to/your/logs/ | tail -n +11)
-1
(数字の1)のオプションは、安全のために、単一の行に各ファイルを印刷します。-f
オプションは、rm
ときのために、存在しないファイルを無視するように指示ls
何も返しませんが。
/path/to/your/logs
に、正しいパスを入力するために構成されています。バグを見つけるには、パーツls -t /path/...
をls -t /path/... | tail -n +11
単独で実行し、結果が正しいかどうかを確認します。
+
番号の前に注意してください。それは作るtail
最後のn個の要素が、n番目から始まるすべての要素を印刷しません。再度チェックインすると、コマンドはすべての状況で最新の10個のファイルより古い要素のみを確実に削除するはずです。
ls
あなたは、ように、ファイル名、パスではなく、プリントrm -f
、現在のディレクトリ内のファイルを削除しようとします
どうやら構文解析ls
は悪です。
各ファイルが毎日作成され、過去10日以内に作成されたファイルを保持したい場合は、次のことができます。
find /path/to/files -mtime 10 -delete
または、各ファイルが任意に作成される場合:
find /path/to/files -maxdepth 1 -type f -printf '%Ts\t%P\n' | sort -n | head -n -10 | cut -f 2- | xargs rm -rf
-mtime 10 -delete
正確に10日前に変更されたファイルのみを削除します。古いファイルは削除されません。-mtime +11 -delete
11日以上前に変更されたファイルを削除し、過去10日間のログファイルを残します。
%p
代わりにの使用%P
が必要だと思いprintf
ます。それ以外の場合はrm -rf
機能しません。
アイザックのアプローチを少し変更しました。
希望のパスで動作するようになりました:
ls -d -1tr /path/to/folder/* | head -n -10 | xargs -d '\n' rm -f
ここから:
#! /bin/sh
# keepnewest
#
# Simple directory trimming tool to handle housekeeping
# Scans a directory and deletes all but the N newest files
#
# Usage: cleanup <dir> <number of files to keep>
#
# v 1.0 Piers Goodhew 1/mar/2007. No rights retained.
if [ $# -ne 2 ]; then
echo 1>&2 "Usage: $0 <dir> <number of files to keep>"
exit 1
fi
cd $1
files_in_dir=`ls | wc -l`
files_to_delete=`expr $files_in_dir - $2`
if [ $files_to_delete -gt 0 ]; then
ls -t | tail -n $files_to_delete | xargs rm
if [ $? -ne 0 ]; then
echo "An error ocurred deleting the files"
exit 1
else
echo "$files_to_delete file(s) deleted."
fi
else
echo "nothing to delete!"
fi
busybox(ルーター)にはエレガントなソリューションが必要でした。すべてのxargsまたはアレイソリューションは役に立たなかった-そのようなコマンドはありません。findおよびmtimeは、必ずしも10項目ではなく10項目について話しているため、適切な答えではありません。Espoの答えは、最短で最もクリーンで、おそらく最も一般的なものでした。
スペースのエラーと、ファイルを削除しない場合は、どちらも単純に標準的な方法で解決されます。
rm "$(ls -td *.tar | awk 'NR>7')" 2>&-
もう少し教育的なバージョン:awkを異なる方法で使用すれば、すべてを実行できます。通常、このメソッドを使用して、awkからshに変数を渡します(返します)。できないことを常に読んでいると、私は違うことを請います:ここに方法があります。
ファイル名のスペースに関して問題のない.tarファイルの例。テストするには、「rm」を「ls」に置き換えます。
eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}')
説明:
ls -td *.tar
すべての.tarファイルを時間でソートしてリストします。現在のフォルダー内のすべてのファイルに適用するには、「d * .tar」部分を削除します
awk 'NR>7...
最初の7行をスキップします
print "rm \"" $0 "\""
行を作成します:rm "ファイル名"
eval
それを実行する
を使用しているためrm
、スクリプトでは上記のコマンドを使用しません!賢明な使用法:
(cd /FolderToDeleteWithin && eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}'))
ls -t
コマンドを使用する場合、次のような馬鹿げた例に害はありません:touch 'foo " bar'
およびtouch 'hello * world'
。実際にそのような名前のファイルを作成することはありません!
サイドノート。このように変数をshに渡したい場合は、単にprintを変更します。
print "VarName="$1
変数VarName
をの値に設定します$1
。複数の変数を一度に作成できます。これVarName
は通常のsh変数になり、後でスクリプトまたはシェルで通常使用できます。そのため、awkを使用して変数を作成し、それらをシェルに戻すには:
eval $(ls -td *.tar | awk 'NR>7 { print "VarName="$1 }'); echo "$VarName"