web-dev-qa-db-ja.com

複数のファイルで最初の一致を見つける方法

Findコマンドで、複数のファイルの文字列またはパターンの最初の一致または出現を検索する方法はありますかそれぞれの中で?私は通常の構文を使用しています:

 find dir -iname '*.ext' -exec command 'pattern' {} \;

(私もたまたま-exec pdfgrepでPDFを検索していますが、それは一般的な問題の特殊なケースであり、後でまたは個別に処理される可能性があると思います。)

これは、-quitまたはhead -n 1でfindを使用して検索から最初の結果を生成するというよくある問題と同じではないことに注意してください。

4
gaberlunzie

GNU grep-mオプションを使用するだけで、(例では)1回の一致後にファイルの読み取りが停止します。

find dir -iname '*.ext' -exec grep -m 1  'pattern' {} \;
8
suspectus

あなたはawkスクリプトでそれを行うことができます:

find dir -iname '*.ext' -exec awk '/pattern/{print;exit}' {} \;
2
Kevin

検索コマンドが最初の一致後に停止する方法がない場合は、その結果をフィルタリングして、最初の出力行command 'pattern' /path/to/file | head -n 1のみを保持できます。コマンドは、headが終了するとSIGPIPEシグナルを受信するため、バッファリングのためにさらにいくつかの一致を探し続ける可能性がありますが、一致が多い場合はファイルの終わりの前に停止します。

(パイプを設定するために)シェルコマンドを実行する必要があるため、shからfindを呼び出す必要があります。引用符に注意してください。外側のシェルには1層の引用符が必要であり、findで始まるシェルには別の層が必要です。内側のシェルコマンドの周りに一重引用符を配置し、'\''ハック(一重引用符リテラルを終了し、リテラル一重引用符の場合は\'、同じ息で新しい一重引用符リテラルを開始)を使用して一重引用符で作業できます。パターンに別の引用符が必要です(パターンに'として表した'\''が含まれている場合を除き、その場合は'\'\\\'\''にする必要があります)。

find dir -iname '*.ext' -exec sh -c 'command '\''pattern'\'' "$0" | head -n 1' {} \;

パターンを引用することを心配する代わりに、それを外に置いてパラメータとして渡すことができます。

find dir -iname '*.ext' -exec sh -c 'command "$0" "$1" | head -n 1' 'pattern' {} \;

1つのシェルのみを呼び出してファイルをループする方が少し速くなります。

find dir -iname '*.ext' -exec sh -c '
    for f; do command "$0" "$f" | head -n 1; done
' 'pattern' {} +