完全なスクリプト。

完全なスクリプト。

設定された制限を超えると、古いファイルを消去するスクリプトがあります。

私は次のコマンドを持っています:

/bin/rm -f `/bin/ls -t $bkup_p/mysql.daily/*  2> /dev/null | /bin/awk 'NR>'5`

$bkup_p に空白がある可能性があるため動作します。

/bin/rm -f `/bin/ls -t "$bkup_p/mysql.daily/*"  2> /dev/null | /bin/awk 'NR>'5`

しかし、これはうまくいきません。問題のファイルは表示されず、空です。

答え1

Bash は、変更時間に基づいてファイルをフィルタリングし、そのファイルに対してコマンドを実行するときにはあまり便利ではありません。

z-shellを試してみることをお勧めします。まずを実行してzshから

rm -i -- "$bkup_p"/mysql.daily/*(DN.Om[1,5])

これにより、特定のディレクトリで最も古い5つの一般的なファイルが削除されます。これはあなたが望むものかもしれません。明らかに、これは必要に応じて最終的にrm -i変更されますrm -f

5 つの最新のファイルを削除するには、次の手順を実行します。

rm -i -- "$bkup_p"/mysql.daily/*(DN.om[1,5])

さて、それがどのように機能するか。内部のすべては、()基本的に必要に応じてファイルをフィルタリングするglob修飾子です。

  • Dドットファイル(で始まるファイル.)を含む
  • N一致するものがない場合は、エラーを報告しないでください。
  • .一般ファイルのみ選択
  • om修正時間でソート(Om逆順)
  • [1,5]リストから5つのファイルのみを選択してください。

私はこれらすべてがファイル名の特殊文字(スペース、改行文字など)に対して機能する必要があると思います。

答え2

他の人が言ったように、lsこの目的には使用しないでください。しかし、あなたの環境にもっとスマートなものがない場合注意事項をご覧ください。、あなた可能ファイル名が次のような場合十分:空白や印刷できない文字、特にシェルからワイルドカードとして解釈されない文字(少なくとも?*[])がありません。

Perlのようなものを使ってファイルを並べ替えるか、ファイル名に日付を入れてグローバル順序に依存する方が良いでしょう。


つまり、2番目のスニペットではアスタリスクが引用されているため、ワイルドカードは発生しません。存在しない項目のエラーが表示されますが、some dir/mysql.daily/*エラー出力をリダイレクトしたため表示されません。

スペースのあるファイル名は、コマンド置換の出力がスペースに沿って分割され、次の問題が発生するため、次のようにsome dir/fooなります。削除されるので、何も存在しないことを願っています。rmsomedir/foo

ディレクトリ名にのみスペースが含まれている場合は、cdそのディレクトリに最初に入れることができます。または、IFSデフォルトのスペース、タブ、改行の代わりに改行のみを含めるように設定します。 NASに言及した場合、Busyboxがある可能性が高くなります。これはbusyboxとbashで動作し、ファイル名を1行に1つずつ印刷します。

IFS=$'\n'
printf "%s\n" $( ls -t "$bkup_p/mysql.daily/"* | tail -n +6 )

正常に動作すると確信している場合は、ファイルを削除するにはにprintf "%s\n"置き換えてください。rm

答え3

ls解析された出力は、新しいコマンドにパイプするために出力形式を正しく指定せず、移植性の問題があるため使用しないことをお勧めします。
私はこのようなことを試みます

find $bkup_p/mysql.daily/ -type f -a -mtime +7 -a -name "*.sql" -a -exec rm -f {} +

メモ:

  • "*.sql"必要に応じてこの設定を変更してください。
  • -mtime +7意味*このファイルが(+)7日前に変更された場合は、必要に応じてこのファイルも変更できます。

何があっても常に10個の最新ファイルを持っていることを確認したい場合(そしてGNUも持っているfind)試してみることができます。

find $bkup_p/mysql.daily/ -maxdepth 1 -type f -a -printf "%T+\t%p\n" | sort -r | sed -n '10,$p' | awk '{print $2}' | xargs rm -f

find演算子を使用して出力をフォーマットする方法の詳細については、-printf以下を参照してください。

man find | less '+/^\s*-printf'

答え4

動作しない問題*は、参照時に拡張されないためです。

次の結果をecho *以下と比較してくださいecho "*"


安定した解決策は、各配列の場所に1つのファイルを持つ配列を使用することです。

運が良く、結果が以下を裏付けるならば-printf:

dir="$bkup_p/mysql.daily/"

find "$dir" -printf '%T@:%i\n'

すべてのファイル名は使用されません。各ファイルは1行です。 1行には数字、オプションのドット、コロンのみが含まれます。

これは簡単にソートできます。

find "$dir" -printf '%T@:%i\n' | sort -rn

最も単純な配列は位置パラメータです。
これにより、ディレクトリ内のすべてのファイルが場所引数のリストに設定されます。

set -f; set -- $(find "$dir" -printf '%T@:%i\n' | sort -n )

set -fは、ワイルドカードでもあるファイル名の拡張を防ぎます*。最初の6つのファイル名を削除(削除)するには、次の手順を実行しますshift

shift 5

残りのファイルに必要な操作を実行します。

for    f
do     rm -f "$(find "$dir" -inum "${f#*:}")"
done

完全なスクリプト。

フルスクリプト(すべてのファイル名に対して強力です)は次のとおりです。

dir="$bkup_p/mysql.daily/"

set -f
set -- $(find "$dir" -type f -printf '%T@:%i\n'|sort -rn)
shift 5

for    f
do     rm -f "$(find "$dir" -inum "${f#*:}")"
done

関連情報