ツール

チェック用のシェルスクリプトに find ... || echo '✅ なし' と書いたところ、該当ファイルが0件のときに「✅ なし」が表示されず、何も出力されないまま終わりました。原因は find が「1件も見つからなかった」を失敗として扱わないことです。終了コードが0になるので || の右側が実行されません。対処は終了コードで分岐せず、出力を変数に入れて空かどうかで判定することです。

0件でも終了コードは0になる

空のディレクトリに対して find を実行し、終了コードを見ると分かります。

mkdir -p testdir
find testdir -name '*.php' -type f; echo "exit=$?"
exit=0

該当ファイルは1つもありませんが、終了コードは0(成功)です。find にとっては「探す処理が正常に終わった」ので成功であり、見つかった件数は成否と関係ありません。

そのため、フォールバックを || で書くと動きません。

find testdir -name '*.php' -type f || echo '✅ なし'
(何も表示されない)

grep と混同すると踏みます。grep は該当なしで終了コード1を返すので || echo が期待どおり動きます。この違いを意識していないと、片方で通用した書き方をもう片方に持ち込んで静かに壊れます。

チェックスクリプトでは「何も出ない」が一番困る

この挙動が厄介なのは、失敗の仕方が無言だからです。今回はサーバーの点検スクリプトで、アップロード先ディレクトリに不審なPHPファイルが置かれていないかを確認する用途でした。

正常なら0件なので、本来は毎回「✅ なし」と出るべき場所です。ところが実際の出力は見出しだけが表示され、その下が空欄になります。異常があって出力されなかったのか、正常で0件なのかが区別できません。

チェック項目としては、正常であることを明示できないと意味がありません。「何も出ていないから大丈夫だろう」と読み手に推測させる時点で、チェックとして機能していないからです。

出力を変数に入れて空判定する

終了コードを使わず、結果の中身で分岐させます。

FOUND=$(find testdir -name '*.php' -type f 2>/dev/null)
if [ -n "$FOUND" ]; then
  echo "$FOUND"
  echo '⚠️ 不審なPHPあり'
else
  echo '✅ なし'
fi

[ -n "$FOUND" ] は変数が空でなければ真になります。0件なら FOUND は空文字列なので else に入り、正常が明示されます。ファイルがある場合は一覧と警告の両方が出ます。

空のディレクトリと、ファイルが1つあるディレクトリで実際に試すとこうなります。

testdir/empty: ✅ なし
testdir/has: ⚠️ あり -> testdir/has/shell.php

どちらのケースも明示的に結果が出ます。変数をダブルクォートで囲むのは忘れないようにします。囲まないと、空のときに [ -n ] という形になって常に真と評価される場合があります。

件数で判定したい場合

ファイル名が不要で件数だけ見たいなら、wc -l で数えて比較する書き方もあります。

COUNT=$(find testdir -name '*.php' -type f 2>/dev/null | wc -l | tr -d ' ')
[ "$COUNT" -gt 0 ] && echo "⚠️ ${COUNT}件" || echo '✅ なし'

wc -l の出力は環境によって空白が付くので tr -d ' ' で削っています。件数が閾値を超えたら警告したい、という条件を書きたいときはこちらが素直です。

ファイル名も知りたい場合は変数に入れる方式のほうが扱いやすいので、用途で選べば十分です。どちらにしても、find の終了コードに判定を任せないことが要点になります。