異なるディレクトリからすべてのファイルを削除し、最新のファイルのみを20ファイル保持したいと思います。これはこれを行うための正しいコマンドですか?
ls -t1 /mnt/dwh/ftp/dwh_ftp_cbs/ARLOGS/ | tail -n +22 | xargs rm -f
あなたのコマンドには多くの欠点があります。たとえば、ls
の出力の処理は、一種のカテキズムです。 この記事 これを行わない理由を参照してください。
このアプローチでは、noGNU拡張機能を使用し、bash、zsh、ksh93、dash、およびashでテストされています。
for f in * .*; do
[ -f "$f" ] && printf "%s " $(Perl -e 'print((stat("$ARGV[0]"))[9])' -- "$f") && \
printf "%s\0" "$f";
done | tr '\0\n' '\n\0' | sort -k1nr | \
sed "1,20d;s/'/'\"'\"'/g;s/[^ ]* \(.*\)/rm -f -- '\1';/" | tr '\0' '\n' | sh
これは、私が作成できた最も奇妙なファイル名です。これでも動作します。
touch -- '--a'"'"'b"c
d$e\nf\r!g;h^i`j(k)l*m%n=o?p.txt'
または、「ジャンプアウト」しようとするファイル名:
touch '\'"'"'echo test '"'"'\'
zsh
および glob-qualifiers の場合:
print -rl -- *(D.Om[1,-21])
最後の(最後に変更された)20を除くすべての通常ファイルをリストします。D
は隠しファイルを選択し、.
は通常のファイルのみを選択します。Om
はmtimeで逆ソートすることを意味します(とても古いものから)と[1,-21]
最初から21番目から最後までを選択します。
結果に満足したら、print -rl
with rm
:
rm -- *(D.Om[1,-21])
膨大な数のファイルがある場合は、引数リストが長すぎるのを避けるためにzargs
を使用する必要があるかもしれません。
autoload zargs
zargs ./*(D.Om[1,-21]) -- rm
ls -t1 /mnt/dwh/ftp/dwh_ftp_cbs/ARLOGS/ | tail -n +22 | xargs rm -f
ls
の出力にはファイルの名前のみが含まれ、フルパスは含まれないため、機能しません。名前が.
で始まるファイルもスキップします。
cd /mnt/dwh/ftp/dwh && ls -At1 | tail -n +21 | xargs rm -f --
それでも解決しますが、空白、改行、アポストロフィ、バックスラッシュ、二重引用符を含むファイル名(および、ロケールで有効な文字を形成しないバイトを含むファイル名)にはまだ問題があります。
(export LC_ALL=C
cd /mnt/dwh/ftp/dwh && ls -At1 |
tail -n +21 |
sed 's/"/\\"/g;s/.*/"&"/' |
xargs rm -f --
)
それらのほとんどは修正されますが、改行文字を含むファイル名にはまだ問題があります。問題は、ls -At1
の出力が後処理できないことです。
ls -Atd1 ./.* ./*
の出力は後処理できますが(./
プレフィックスは、各ファイル名が出力のどこから始まるかを示しますが、簡単ではありません)、引数の数が上限に達するリスクがあります。そのようにファイル名のリストをls
に渡すことによってコマンドに渡されます。
最善の方法は グロブでそのソートを実行できるシェルを使用する 、またはGNUシステムでのみ作業する必要がある場合は、GNU拡張機能に依存することです。
cd /mnt/dwh/ftp/dwh &&
find . ! -name . -Prune ! -type d -printf '%T@\t%p\0' |
tr '\0\n' '\n\0' |
sort -rn |
tail -n +21 |
cut -f 2- |
tr '\0\n' '\n\0' |
xargs -r0 rm -f
ここでは、タイプdirectoryのファイルを除外しています。これは番号付けに影響しますが、おそらくあなたが望むとは思わないので、あなたが望むものに近いでしょう。ディレクトリを削除します。ディレクトリを削除する場合は、-type d
を削除し、-r
オプションをrm
に追加します。
または:
eval "set -- $(COLUMNS=4294967295 ls -Atx --quoting-style=Shell-always)"
if [ "$#" -gt 20 ]; then
shift 20
printf '%s\0' "$@" | xargs -r0 rm -f --
fi
または、Perl
、python
、Ruby
..などのジェネリックプログラミング言語を使用します。