GNU findの「-or」フラグが原因で式が予期しない方法で評価されるのはなぜですか?

GNU findの「-or」フラグが原因で式が予期しない方法で評価されるのはなぜですか?

以下は期待どおりに機能します。

[pitserver ~]% sudo find /home/pitserver/operator -uid 11 -exec ls -nld {} +
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28   32 Oct  3  2005 /home/pitserver/operator/.amandahosts
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

以下はすべてのファイルを一覧表示すると予想していますが、すべてのファイルを一覧表示します。とは別に .amandahosts:

[pitserver ~]% sudo find /home/pitserver/operator -name '.amandahosts' -or -uid 11 -exec ls -nld {} +        
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

なぜですか?

ベストアンサー1

~によるとman find、連結(暗黙的な "and"演算子)が演算子-orよりも優先されるため、引数は次のように評価されると予想できます。

( -name '.amandahosts' -or -uid 11) と( -exec ls -ld {} +)

実際に find コマンドに括弧を追加すると、期待どおりに動作します。

[pitserver ~]% sudo find /home/pitserver/operator '(' -name '.amandahosts' -or -uid 11 ')' -exec ls -nld {} +
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28   32 Oct  3  2005 /home/pitserver/operator/.amandahosts
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

ただし、findは実際にパラメータを次のように解釈します。

-name '.amandahosts')または(-uid 11 -exec ls -ld {} +

ここに見られるように:

[pitserver ~]% sudo find /home/pitserver/operator -name '.amandahosts' -or '(' -uid 11 -exec ls -nld {} + ')'
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

ここで起こるのは、ORが短絡されたことです。-uid 11 -exec ls -ld {} +"-or"( ) の 2 番目の部分を評価します。〜しない限り最初の部分(-name '.amandahosts')の計算結果は次のとおりです。間違った。したがって、findは-exec ...ファイル名が指定されていない場合にのみ実行されます'.amandahosts'。これがどのように機能するかを理解する1つの方法は、次が成功するかどうかを観察することです。

[pitserver ~]% sudo find /home/pitserver/operator -name '.amandahosts' -exec ls -nld {} + -or -uid 11 -exec ls -nld {} +
-rw------- 1 11 28 32 Oct  3  2005 /home/pitserver/operator/.amandahosts
drwxr-xr-x 2 11 28 4096 Jan 30  2006 /home/pitserver/operator
-rw------- 1 11 28  700 Jan 30  2006 /home/pitserver/operator/.viminfo
-rw------- 1 11 28   65 Jan 30  2006 /home/pitserver/operator/.Xauthority

この問題を解決する最善の方法は、「or」演算子を使用するときは常に括弧を使用するようです。これは、所望の動作を正確に提供するためである。

'(' -name '.amandahosts' -or -uid 11 ')' -exec ls -nld {} +

おすすめ記事