find
特定のファイル セットのサイズを一覧表示するコマンドを使用しようとしていますが、出力が得られません。使用するコマンドは次のとおりです。
find POD -type f -name *.mp3 -or -name *.ogg -ls
出力は生成されません。一方:
find POD -type f -name *.mp3 -or -name *.ogg
出力が生成されるので、次のアクションも試しました:
-printf "%p %k KB\n"
-exec ls -ls '{}' \;
-print0
しかし、これらすべては出力を生成しません。これらのアクションのいずれかを別の式で使用すると、例:
find . -maxdepth 1 -type f -printf "%p %k KB\n"
期待通りの出力が得られました。何が問題なのか分かる人はいますか? 実行しているのは:
Linux irimi 3.10.37-1-MANJARO #1 SMP Mon Apr 14 20:56:29 UTC 2014 x86_64 GNU/Linux
別名、最新の Manjaro Linux ディストリビューション。私が使用するシェルは/bin/bash
バージョンです4.3.8(1)-release
。
SHELLOPTS
私の環境変数の内容は次のとおりです。
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
私のBASHOPTS
環境変数は次のとおりです:
cdspell:checkwinsize:cmdhist:complete_fullquote:dotglob:expand_aliases:extglob:extquote:force_fignore:histappend:hostcomplete:interactive_comments:nocaseglob:progcomp:promptvars:sourcepath
繰り返しになりますが、これをデバッグするためのご協力をいただければ幸いです。
答え1
罠があるおよび/またはfind
.のキーワードは、or
アクション (-ls
この例では ) を含む、後続のすべてのパラメーターに適用されます。のない(または が付属している)and
式は、読み取り順に評価され、最終停止は false になります。 はありません。or
and
implicit ()
つまり、その命令はfind POD -type f -name *.mp3 -or -name *.ogg -ls
、
- ファイルの検索(PODディレクトリから開始) --- ファイルが見つからない場合:STOP
- そうでない場合 (ファイルが見つかった場合) パターン マッチングをチェックします
*.mp3
--- パターンが一致する場合 : STOP ! (OR
ここから適用され、前のコマンドが失敗した場合にのみ適用されます (ただし、前のコマンドのみであり、前のコマンド グループは失敗しません))
また、コマンド ラインに実行ステートメント ( -ls
、、-exec
.... -print
) を追加すると、暗黙のコマンドはなくなり、-print
1) のすべての条件が true (ファイルとパターンが一致) の場合は何も実行されません。最後のものを削除すると、各条件分岐の最後に-ls
暗黙の分散が存在します。-print
- パターンが一致しない場合は、パターンに一致するもの (ファイル/ディレクトリ) を検索し
*.ogg
、それらを一覧表示します (これは-ls
条件コマンドではなく、前のコマンド/テストの「パターン」が true の場合にのみ実行されます*.ogg
)。ただし、1) のため、2) は mp3 ファイル以外のファイルに対してのみ評価されます。ファイルがない場合、.ogg
何も表示されません。
解決策1 各論理分岐で実行コマンドを繰り返す
find POD -type f -name "*.mp3" -ls -or -name "*.ogg" -ls
解決策2(シェルで保護された)括弧を追加
find POD -type f \( -name "*.mp3" -ls -or -name "*.ogg" \) -ls
注記 現在のディレクトリでシェルパターンの評価を回避するには、パターンを保護する必要があります。
答え2
評価順序(明示的な優先順位がない)が原因だと思います。例えば、
-name '*.mp3' -o -name '*.ogg' -ls
-name '*.ogg'
が偽と評価された場合、ls
アクションは実行されません。括弧を使用してOR式をグループ化することで、期待どおりの動作を得ることができます。たとえば、
$ ls tests
file1.mp3 file2.mp3 file3.mp3
それから
$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print
tests/file3.mp3
tests/file1.mp3
tests/file2.mp3
一方
$ find tests -name '*.mp3' -o -name '*.ogg' -print
出力は生成されません。
$ find tests -name '*.mp3' -o -name '*.ogg'
は暗黙的に次のように扱われるため、特別なケースである。
$ find tests \( -name '*.mp3' -o -name '*.ogg' \) -print
find
また、シェルがそれらを展開しないように、コマンド内のシェル グロブを引用符で囲むかエスケープするのが良い方法であることにも注意してください。findNON-BUGS
のマニュアルページのセクションを参照してください。