可能性のある複製:
最も古いファイルを移動するためのシェルスクリプト?
バックアップが必要なx
他のディレクトリを格納するバックアップディレクトリがあります。別のディレクトリがバックアップに移動する前に実行するものが必要です。ディレクトリの数がx
に達したかどうかを確認し、達した場合は、最も古いディレクトリを削除します。
bash
スクリプトで実行する必要があります。
ls
の出力の解析は 信頼できない です。
代わりに、find
を使用してディレクトリを検索し、sort
を使用してタイムスタンプ順にディレクトリを並べ替えます。例えば:
_IFS= read -r -d $'\0' line < <(find . -maxdepth 1 -type d -printf '%T@ %p\0' \
2>/dev/null | sort -z -n)
file="${line#* }"
# do something with $file here
_
最初に、find
コマンドは、現在のディレクトリ(_.
_)のすべてのディレクトリを検索しますが、現在のディレクトリ(_-maxdepth 1
_)のサブディレクトリは検索しません。次に出力します。
タイムスタンプは重要です。 _%T@
_の_-printf
_形式指定子は、ファイルの「最終変更時刻」(mtime)を示すT
と、小数秒を含む「1970年からの秒数」を示す_@
_に分類されます。 。
スペースは単なる任意の区切り文字です。ファイルへのフルパスは後で参照できるようにするためのものであり、NULL文字はファイル名に含まれる不正な文字であるためターミネーターであり、そのため、パスへのパスの最後に到達したことを確実に知らせますファイル。
_2>/dev/null
_を含めて、ユーザーがアクセス許可を持っていないファイルは除外しましたが、除外されているというエラーメッセージは表示されません。
find
コマンドの結果は、現在のディレクトリ内のすべてのディレクトリのリストです。リストはsort
にパイプで渡され、次のように指示されます。
-z
_ NULLを改行ではなく行終了文字として扱います。-n
_数値順に並べ替えSeconds-since-1970は常に上がるので、タイムスタンプが最も小さい番号のファイルが必要です。 sort
の最初の結果は、最も小さい番号のタイムスタンプを含む行になります。あとは、ファイル名を抽出するだけです。
find
、sort
パイプラインの結果は プロセス置換 を介してread
に渡され、そこでstdin上のファイルであるかのように読み取られます。
read
のコンテキストでは、IFS
変数に何も設定しません。これは、空白が区切り文字として不適切に解釈されないことを意味します。 read
には、エスケープ拡張を無効にする_-r
_と、行末の区切り文字をNULLにする_-d $'\0'
_が伝えられ、find
、sort
パイプラインからの出力と一致します。
タイムスタンプとスペースが前に付いた最も古いディレクトリパスを表すデータの最初のチャンクは、変数line
に読み込まれます。次に、 パラメータ置換 を式_#*
_で使用します。これは、文字列の先頭から最初のスペースまでのすべての文字を、スペースを含めて何も置き換えないだけです。これにより、変更タイムスタンプが取り除かれ、ファイルへの完全なパスのみが残ります。
この時点で、ファイル名は_$file
_に保存されており、_rm -rf "$file"
_を含め、ファイル名を使用して好きなことができます。
いいえ。より単純な方法はバグがあります。
_ls -t
_を使用し、tail
にパイプすると、ファイル名に改行が含まれるファイルで中断されます。 rm $(anything)
の場合、名前に空白が含まれるファイルは破損の原因になります。 rm "$(anything)"
の場合、名前の末尾に改行があるファイルは破損の原因になります。
おそらく、特定のケースでは、より単純な方法で十分であることが確実にわかっていますが、そうすることを避けることができるのであれば、スクリプトにそのような仮定を記述しないでください。
_#!/usr/bin/env bash
dir="$1"
min_dirs=3
[[ $(find "$dir" -maxdepth 1 -type d | wc -l) -ge $min_dirs ]] &&
IFS= read -r -d $'\0' line < <(find "$dir" -maxdepth 1 -printf '%T@ %p\0' 2>/dev/null | sort -z -n)
file="${line#* }"
ls -lLd "$file"
_
最初にdirカウントをチェックするため、問題に対するより完全なソリューション。
あなたは次のようなものを使うことができます:
#!/bin/sh
keep=3
while [ `ls -1 | wc -l` -gt $keep ]; do
oldest=`ls -c1 | head -1`
echo "remove $oldest"
rm -rf $oldest
done
find . -type d -maxdepth 1
の代わりにls
を使用します。これは、ディレクトリに使用する命名スキーマによって異なります。それらが名前で自然に正しくソートされている場合は、find
、sort
およびhead
またはtail
を使用して、最も古い/最新のディレクトリを取得できます。 ls
アプローチは、ctime属性を使用してソートします。