Bashスクリプト - 最近変更されたファイルがあるかどうかを確認する

Bashスクリプト - 最近変更されたファイルがあるかどうかを確認する

私は、特定のディレクトリのファイルが最近変更されたことを確認する必要があるスクリプトを作成しています。簡単に使えると思いましたが、find一致するものが見つからなくても成功を報告します。

$ touch afile
$ find . -mtime -1 -iname ????*
./afile
$ echo $?
0
$ find . -mtime +1 -iname ????*
$ echo $?
0

(「.」を除外するためにiname述語を使用しましたが、同じ動作-type f

ls私はこのような出力を解析したくありません。性格が悪いかもしれません。

を使用すると、test -n "$(find . -mtime -1 -iname ????*)"期待した結果が得られるようですが、特にエレガントなソリューションではないようです。

どのファイルが変更されたかを知る必要はありません。ただ最近ファイルが変更されただけです(「最も最近」は通常1日です)。

もっと良い方法がありますか?

(Googleで検索すると、簡単な検索を実行する方法に関するSEO関連の不満がたくさんあります。)

答え1

はい、ご覧のとおり、findの終了コードを使用してこのようなことを行うことはできません。終了コードは、ファイルが見つかったかどうかではなく、コマンドが正常に実行されたかどうかに関連します。結局のところ、ファイルが見つからないのは失敗ではなく成功です。ファイルがない正しい結果が得られます。これman findの説明は次のとおりです(GNU findから引用)。

終了ステータス

すべてのファイルが正常に処理されると、find は状態 0 で終了し、エラーが発生すると状態は 0 より大きくなります。これは意図的に非常に広範な説明ですが、戻り値がゼロでない場合は、結果の精度に依存しないでください。探す

特定のエラーが発生すると、指定されたすべての操作を完了せずにfindがすぐに停止することがあります。たとえば、一部の始点はまだ確認されていないか、一部の保留中のプログラム呼び出しがある可能性があります。 -exec...{}+または-execdir...{}+まだ実装されていない可能性があります。

あなたは実際にそれを使用することができます-n $(find ...)。私はそこに実際に問題を見ません。ファイル名は含めることができないため、NULこれが壊れる可能性がある状況は考えられません。もっときちんとしたい場合は、配列を使用してから、配列の要素数を超えたかどうかをテストできます0。このような:

$ findResults=( $(find . -mtime -1 -iname '????*' | head -n1) )
$ [[ ${#findResults[@]} -gt 0 ]] && echo "Found files!" || echo "No files found!"
Found files!

$ findResults=( $(find . -mtime +1 -iname '????*' | head -n1) )
$ [[ ${#findResults[@]} -gt 0 ]] && echo "Found files!" || echo "No files found!"
No files found!

しかし正直、これが[[ -n $(find ...) ]] && echo found || echo nope

答え2

zshを使用して、

if ()(($#)) **/????*(NDY1m-1); then
  echo There are files or directories last modified within the last 24 hours
fi
  • () {body} args定義と実行匿名関数(($#))ここの本文は、(パラメータの数)が0以外の場合にtrueを返す算術式です。$#
  • **/すべてのレベル(レベル0を含む)のディレクトリ、Extendedglobの略語です(*/)#。それ自体は考慮されません.。考慮したい場合**/に置き換えることができます。{.,**/}
  • N: 空のボールグローバル予選: 一致するものがなくても文句を言うのではなく、匿名関数に空のリストを渡してください。
  • D:dotglob、隠しファイルをスキップしないでください。
  • Y1: 最適化で最初の一致で停止
  • m-1:最後mの修正は最後の日(24時間)で行われました(例:findの)-mtime -1

を使用すると、名前が4文字以上のファイルを一致させるために代わりにset -o extendedglob使用できます。?(#c4,)????*

答え3

if find . -name '????*' -mtime -1 | LC_ALL=C grep -q '^'; then
  echo There are files last modified within the last 24 hours
fi

一致するファイルが多い場合は、grep -q入力行を読み込んで終了し、find次にパイプに何かを書き込むと終了するため、少し効率的になる可能性があります。

パイプの出力はパイプに入るとバッファリングされるため、最初のファイルが見つかるとfindパイプは終了しません。

GNUまたはFreeBSDを使用すると、find次のことができます。

if [ -n "$(find . -name '????*' -mtime -1 -print -quit)" ]...

NetBSDでは、これはマイナーな最適化で置き換えることができる-exitGNUを使用するのと同じです。find-print-printf .

次のこともできます。

if [ -n "$(
  find . -name '????*' -mtime -1 -exec sh -c 'echo .; kill -s PIPE "$PPID"' ';'
  )" ]...

wherefind呼び出しはsh何かを出力し、その親を殺します。

答え4

mtreeバイナリでいっぱいのディレクトリが悪意のあるコードや破損したコードで上書きされていないこと、またはファイルセットが誤って変更されていないことを確認したいユースケース(データまたはメタデータ)などの操作用に特別に設計されています。

-c要約を含む目次()の参照ファイルを作成()します。my_dir.mtree-p my_dir-K sha256

$ sudo mtree -c -p my_dir -K sha256 > my_dir.mtree

次回ファイルが変更されたことを確認するには、パスオプションとmtree仕様ファイルのみを指定してmtree再実行してください。-p

$ sudo mtree -p my_dir < my_dir.mtree

他のファイルがリストされます。

関連情報