find:-a演算子が-printと結合されたときに交換できないのはなぜですか?

find:-a演算子が-printと結合されたときに交換できないのはなぜですか?

現在のディレクトリにあるオーディオファイル(MP3など)と、現在のディレクトリまたはその下のどこかに存在するmp3以外のファイル(JPEGなど)にfindを使用するとします。
これに加えて、他のオーディオファイルを含むディレクトリもあります(私を除く例では、文字通りファイル検索から除外する必要があります。

find . \( -type d -name 'exclude_me' -prune \) -o \( -type f -a -iname '*.mp3' -a -print \)

-a(この例では必ずしも必要ではありませんが、明確にするために、いくつかの重複する括弧やその他の演算子を意図的に含めました。)

明示的なオプションの後-print(また参照http://mywiki.wooledge.org/UsingFind)、これは実際には「exclude_me」ディレクトリのすべての内容を省略し、現在のディレクトリから* .mp3ファイルのみを再帰的に一覧表示します。時には(常にそうではありませんが)、aliasコマンドは1行のコードで十分ですが、findコマンドにはパラメータが必要です。終わりライン。
-inameの '*.mp3'パラメータは次のとおりです。今後この-print場合、問題を解決する方法がないようですalias

しかし、単に2つのオプションを変えて数学のように振る舞うのはどうでしょうか?
このように:

find . \( -type d -name 'exclude_me' -prune \) -o \( -type f -a -print -a -iname '*.mp3' \)

.mp3ファイル内にmp3以外のファイル(画像など)が1つ以上ある必要があるという前提条件を設定しました。ディレクトリまたはそのサブディレクトリ。これに対するより明確な証拠を提供するために設立されました。いいえ後ろでは期待どおりに動作します。彼らがなければ、状況はこうなります。バラよりうまくいきます。持つ-iname '*.mp3'1行のコードにはさまざまな仕様がありますが、その仕様のためにmp3以外のファイルも一覧表示されます。それでは、-a演算子が数学のように動作しないのはなぜですか?ここで、「A+B」は「B+A」と同じである。またはfind専門用語として:

\( -type f -a -print -a -iname '*.mp3' \)

同じでなければなりません

\( -type f -a -iname '*.mp3' -a -print \)

それとも?

希望の結果を得る方法はありますか?そして-inameパラメータを行の途中ではなく行の末尾に配置しますか? (醜いハッキングソリューションgrep -v exclude_meなどは除く)

答え1

andorC、C++、C♯、シェル、findなど、多くのプログラミング言語では互換性がありません。

彼らは左から右に怠惰な評価を使用します。つまり、左側の用語が最初に評価され、右側の用語が必要な場合にのみ評価されます。したがって、false and b答えbは常に間違っているため評価されません。ただし、2番目の項がfalseであることをまだ発見していないため、評価されますb and falseb

用語が純粋な関数(述部など)(ブール値を返し、他の操作を実行しない)の場合は違いはありませんが、操作を実行する場合(副作用がある場合)重要です。

-print何かしてみてください。印刷されるので重要です。

副作用(例:-print)を許可するすべてのシステムは評価順序を定義する必要があり、左から右に最も簡単になります。

答え2

彼らは違う。-printPrimary は常に true と評価され、現在のパス名が標準出力に書き込まれます。

あなたが使用するとき:

\( -type f -a -print -a -iname '*.mp3' \)

見つかったすべてのファイルは標準出力として印刷されます。- 印刷の基本動作-iname '*.mp3'、式が真であるか偽であるかに関係なく。

あなたが使用するとき:

\( -type f -a -iname '*.mp3' -a -print \)

-print-iname '*.mp3'部分は、式が真の場合にのみ到達します。したがって、で終わるファイルのみが.mp3印刷されます。

POSIXの定義-a 演算子の検索ように:

式[-a]式

デフォルトの組み合わせ、AND演算子は、2つの基本演算子を並列して暗黙的に使用するか、オプションの-a演算子を介して明示的に使用します。最初の式がfalseの場合、2番目の式を評価しないでください。

この場合、式がtrueの場合はデフォルトで追加されるため、-print使用する必要はありません。-print

式がない場合は、-printを式として使用する必要があります。それ以外の場合、与えられた式にピボット-exec、-ok、または-printが含まれていない場合、与えられた式は次に効果的に置き換えられます。

(与えられた表現) - 印刷

しかし、これによって私を除くfind一致すると、-prune式はtrueと評価されるため、出力に印刷されます。-print2番目の式では省略したため、2つの-print式の末尾に追加されます。次のようになります。

find . \( -type d -name 'exclude_me' -prune \) -print -o \( -type f -a -iname '*.mp3' \) -print

これにより私を除く印刷されます。

いつでも省略できます。私を除く-print出力に2番目の式を明示的に追加します。結果-printとして、2番目の式のみが生成されます。

find . \( -type d -name 'exclude_me' -prune \) -o \( -type f -a -iname '*.mp3' \) -print

または、その後に式を追加し、-prune最初の式がfalseであることを確認してください。

find . \( -type d -name 'exclude_me' -prune -a -name . \) -o \( -type f -a -iname '*.mp3' \)

答え3

エイリアスの代わりにシェル関数を使用してください。

function my_find
{
   exclude_dir="$1"
   shift
   find . \( -type d -name "$exclude_dir" -prune \) -o \( -type f -a -iname "$@" -a -print \)
}

関連情報