テクノロジー · 実用ガイド

find が「paths must precede expression」と表示? コマンドを書き換える前にシェル展開を確認する

このエラーは通常、find が解析する前にシェルやラッパーが引数列を変えたことを示し、開始パスが誤りだとは限りません。実際の argv を記録し、開始点と式を分け、find に渡すパターンを引用し、0件・1件・複数件で試してから破壊的操作を戻します。

未引用ワイルドカードが find の解析前に複数引数へ展開される概念図
概念図:入力文字列ではなく、find が実際に受け取った引数ベクトルを確認します。 Watch at Ease

このメッセージは、find が受け取った開始点と評価式の境界を保てなかったことを意味します。-name の前のディレクトリが誤りだと単独で証明するものではありません。

最も価値のある証拠は実際の引数ベクトルです。シェルやラッパーが find に渡した内容を確認し、各トークンの役割を分類し、0件・1件・複数件で修正を検証してから変更操作を戻します。

1. 元のコマンドと argv 境界を保存する

シェル、作業ディレクトリ、find の版、正確なコマンド、終了値、stderr を記録します。安全なら各引数を個別に引用表示し、秘密をログに残したり eval で再構築したりしません。

対話シェル、スクリプト、別名、変数、ビルドツールを通ると、見た目が同じでも argv は変わり得ます。表示された文字列だけでは不十分です。

2. 一致0件・1件・複数件を再現する

無害なテスト用ディレクトリで同じパターンを試します。未引用の *.txt は1語のまま、1パスに展開して偶然成功、複数パスに展開して追加開始点と解釈、のいずれにもなり得ます。

find 自身に照合させるパターンは引用またはエスケープします。Bash と zsh などの不一致時動作の差は証拠として記録します。

3. 各トークンを開始点か式に分類する

受け取った引数を1行ずつ並べ、本当の開始パス、-name などのテスト、-print などのアクションに分類し、各 primary の引数個数を確認します。

未知のトークンをすべて前へ動かさず、パス、オプション、オペランド、グループ記号、アクションのどれかをインストール済み実装の文書で確認します。

4. 変数とラッパーで境界を守る

Bash の未引用パラメータ展開は単語分割とパス名展開を受けます。複数引数は配列を使い、1引数に保つ値は引用し、別名、関数、サービス、ビルドツールを別々に調べます。

eval や連結した1本の文字列で直さないでください。再解析は空白とワイルドカードの意味を変え、注入経路も作ります。

5. 破壊的操作の前に修正を証明する

まず変更操作を -print に置き換え、0件・1件・複数件、空白や先頭ハイフンを含む名前を確認し、実際のスケジューラから同じ argv が届くことを確かめます。

選択集合が正しい場合だけ、狭い試験範囲と復旧計画の下で -delete や -exec を戻します。診断が消え、出力が正しく、引数の役割が変わらなければ合格です。

シェル展開、開始パス、find 式、ラッパー境界を分ける判断図
概念図:各トークンを役割別に処理し、表示のみのテストで修正を検証します。 Watch at Ease