プログラミング言語や環境設定を中心としたパソコン関連の技術メモです。
主にシステム開発中に調べたことをメモしています。TIPS的な位置付けで、気が向いたときにちまちま更新していきます。
Linux、findの検索パターンに「*」を使うと、たまに「find: パス名は評価式の前に置かなければいけません」と怒られる話。
結論から書くと、「-name」で指定した検索パターンを
「"(ダブルクォート)」なり「'(シングルクォート)」なりで囲んだら解決しました。

find ./ -name *.conf -print

ではなく

find ./ -name "*.conf" -print

とすれば期待通りに動作しますよ。

……ただ、ちょっと腑に落ちないことがあるのですよね(--ゞ
■2016/01/09追記
解決しました。
興味がある方は、このページの下の方をご覧ください。

それでは、詳細を書いていきます。

ちょっくら「/etc」配下の設定ファイル名を抽出しようと思いましてね。
以下のコマンドを実行しました。

cd /etc
find ./ -name *.conf -print


単純にcdコマンドで「/etc」に移動してfindを実行しているだけです。
わざわざcdコマンドも書いている理由は後で分かります。

そんな感じfindを実行したところ、以下のエラーが出ました。

find: パス名は評価式の前に置かなければいけません: dnsmasq.conf
使用法: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

ちなみに環境はCentOS 7です。

ほんで、あれやこれやと調べたところ、
「"(ダブルクォート)」なり「'(シングルクォート)」なりで囲めとの情報を見つけました。

ということで、こんな感じに変更φ(--)

cd /etc
find ./ -name "*.conf" -print


これで、無事に設定ファイル名を抽出できました。
やったね\(--)/

……で終わっても良いのですが、ちょっとだけ腑に落ちないことが残っています。

実は、こうやっても、なんのエラーもなく動くのですφ(--)

cd /
find ./etc/ -name *.conf -print


あるいは、こうやっても動きましたφ(--)

cd /etc/kernel/
find ./../ -name *.conf -print


「"」や「'」で囲んでいないのに普通に動きます。
「/etc」直下でfindしたときだけ、引用符で囲まないとエラーになりました。

何でだべ(--?

常に「"(ダブルクォート)」なり「'(シングルクォート)」なりで囲めば良いだけですが、
ちょっと落ち着かない気分です(--ゞ

取りあえず、完了?\(-A-)/

■2016/01/09追記
あ~!分かったぁ!
シェル(bash)が勝手にアスタリスクを展開してるんだ!(ノ∀`)

試しに

cd /etc
sh -x -c "find ./ -name *.conf -print"


を実行したところ、こんな結果になりましたφ(--)

+ find ./ -name asound.conf dnsmasq.conf dracut.conf (中略) yum.conf -print
find: パス名は評価式の前に置かなければいけません: dnsmasq.conf
使用法: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

「*.conf」が、カレントにある「ほげ.conf」に置き換わってます(ノ∀`)

なるほどなるほど。
ということは、こんなコマンドを実行するとφ(--)

cd
sh -x -c "find /etc/ -name *.conf -print"


予想通り、こんな結果になりましたφ(--)

+ find /etc/ -name '*.conf' -print
/etc/resolv.conf
(中略)
/etc/locale.conf

カレントディレクトリに「*.conf」に該当するファイルが無かったので
「*.conf」を文字列と解釈してくれたみたいですね。

だから、カレントディレクトリに「hoge.conf」を作ってから同じコマンドを実行するとφ(--)

cd
touch hoge.conf
sh -x -c "find /etc/ -name *.conf -print"


こんな結果になりますφ(--)

+ find /etc/ -name hoge.conf -print

エラーにはなりませんが「*.conf」が「hoge.conf」に展開されているので
「/etc」配下にある設定ファイルが1つもヒットしません。

さらに、カレントディレクトリに「.conf」なファイルを複数作ってから実行するとφ(--)

cd
rm -f hoge.conf (←分かりやすくするために、前のhoge.confを削除)
touch hoge.conf
touch hoge2.conf
sh -x -c "find /etc/ -name *.conf -print"


エラーになりますφ(--)

+ find /etc/ -name hoge.conf hoge2.conf -print
find: パス名は評価式の前に置かなければいけません: hoge2.conf
使用法: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

「*.conf」が「hoge.conf hoge2.conf」に展開されてからfindが実行されているからです。

「"(ダブルクォート)」なり「'(シングルクォート)」なりで囲めば解決するのは、
シェルが文字列と解釈して展開しなくなるからですね。

「"(ダブルクォート)」なり「'(シングルクォート)」なりで囲んで実行するとφ(--)

cd
rm -f hoge.conf (←分かりやすくするために、前のhoge.confを削除)
rm -f hoge2.conf (←分かりやすくするために、前のhoge2.confを削除)
touch hoge.conf
touch hoge2.conf
sh -x -c "find /etc/ -name '*.conf' -print"


こんな結果になりますφ(--)

+ find /etc/ -name '*.conf' -print
/etc/resolv.conf
(中略)
/etc/locale.conf

「*.conf」を文字列として解釈してくれているので、
期待通りの動作になりました。

ということで、結論は

1.シェルによって「*」が展開された後にfindが実行される
2.「"」か「'」で囲めば文字列として認識されるので「1.」が発生しない


です。

はー、スッキリ\(*´ェ`*)/
スポンサーリンク
 
このエントリーをはてなブックマークに追加 

category:● Linux  thema:パソコンな日々 - genre:コンピュータ  Posted by ササキマコト 

  関連記事