1つの文字列(例:)を含まないが別の文字列(例:)を含むファイルを見つける必要があります.php
。.pl
aaa
bbb
現在、次のコマンドを使用しています。
find /path/ \( -iname '*.php*' -or -name '*.pl*' \) -exec sh -c 'grep -l -v "aaa" {} | grep -l "bbb" {}' \; > resulttofile
検索するファイルが50万個ほどあるのに知りたいです。
- 私のコマンドが正しく機能したら、目のサンプリングを介して肯定的な結果を得ることができます。
- 他の形式(現在の仮想マシンでは約2分かかりますが、より多くのファイルが追加される予定)を使用するか、代わりにまたは両方を組み合わせて使用する方が速い
awk
場合。sed
grep
grep
システムはDebian GNU/Linuxです。
答え1
あなたのコマンドは機能しません。最初のコマンドはgrep
一致しない行を含むすべてのファイルを一覧表示し、2番目のコマンドは処理する"aaa"
独自のファイルを提供するため、最初のコマンドの出力を無視します。したがって、どうかどうかに関係なくgrep
一致するファイルのリストを取得します。"bbb"
それらは含まれています"aaa"
。行一致()grep
がない場合にのみファイルを一覧表示するように要求し、結果ファイルのリストを処理して2番目のファイルにのみ供給する必要があります(または2番目のファイルが最初のファイルで始まるようにする必要があります)。"aaa"
grep -L
xargs
grep
grep
結論は、find
リストされたファイル名がシェルに問題を引き起こさない場合にのみ機能することです。{}
特定のコマンドに直接含めると、sh -c
ファイル名は最終的にシェルコマンドとして解釈されます(参照「find -exec sh -c」を使っても安全ですか?詳細はこちら)。
GNUを使用すると仮定すると、以下は少ないgrep
呼び出しが必要で、より安全です。grep
find /path/ \( -iname '*.php*' -o -name '*.pl*' \) -exec grep -LZ aaa {} + |
xargs -r0 grep -l bbb
これ-or
演算子はGNU拡張ですfind
。使用-o
携帯性のため。
答え2
テストされていませんが、GNU awkを使用して必要に応じて動作しますnextfile
。ENDFILE
find /path/ \( -iname '*.php*' -or -name '*.pl*' \) -exec awk '
/aaa/{a=1} /bbb/{b=1} a&&b{nextfile} ENDFILE{if (b && !a) print FILENAME; a=b=0}
' {} + > resulttofile
上記は複数のファイルに対して一度だけawkを呼び出すので、効率的です。
上記は通常、ファイルの複数のパターンを一致させ、ファイルを完全に読み取った後に一致した組み合わせの結果を評価する方法ですが、次のようになります。@G-Manは「モニカ復元」と言います。で言及コメントaaa
この特定のケースでは成功基準がaaa
存在しないため、一致するエントリから現在のファイルの読み取りを停止して効率を向上させることができます。
/aaa/{a=1; nextfile} /bbb/{b=1} ENDFILE{if (b && !a) print FILENAME; a=b=0}
答え3
findコマンドを使用して、複数の-execディレクティブ(または他のディレクティブ)を連結できます。
find /path \( -iname '*.php*' -or -name '*.pl*' \) -exec grep -q "bbb" {} ";" \
-exec grep -L "aaa" {} ";" > resulttofile
(改行はSEのレイアウトに合わせるためのものです)。