フォルダの最後(最近)20個のファイルを除いてすべて削除[重複]

フォルダの最後(最近)20個のファイルを除いてすべて削除[重複]

他のディレクトリのすべてのファイルを削除し、最新の20個のファイルのみを維持したいと思います。これを行う正しいコマンドですか?

ls -t1 /mnt/dwh/ftp/dwh_ftp_cbs/ARLOGS/ | tail -n +22 | xargs rm -f

答え1

そしてzshグローバル予選:

print -rl -- *(D.Om[1,-21])

最後の(最も最近修正された)20個のファイルを除くすべての一般ファイルが一覧表示されます。
D隠しファイルの選択、.通常のファイルのみの選択、Om逆の並べ替えを意味します。時間(古いものから)そして[1,-21]最後から最初から21日まで選択してください。
結果が満足な場合は、次のようprint -rlに変更してくださいrm

rm -- *(D.Om[1,-21])

ファイルの数が多い場合は、使用をzargs避ける必要があるかもしれません。パラメータリストが長すぎます。:

autoload zargs
zargs ./*(D.Om[1,-21]) -- rm

答え2

ls教義の質問である出力処理などのコマンドには多くの欠点があります。バラよりこの記事なぜこれをしないのですか?

この方法はいいえGNU拡張で、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 '"'"'\'

答え3

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

ここではファイル形式を除外します。目次、これは番号付けに影響しますが、ディレクトリを削除したくないと思うので、おそらくあなたが望むものに近いです。ディレクトリを削除するには、その-type dオプションを削除して 。-rrm

または:

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などの汎用プログラミング言語を使用してください。

関連情報