一部の文字列を含むが別の文字列を含まないファイルを検索するLinuxコマンドとは何ですか?


4

私は特定の文字列ではなく、他の文字列ではなく多くのXMLファイルを検索しようとしていますが、それを行うためのコマンドをまとめるのに問題があります。包含/除外基準に一致するファイル名のみをリストするようにします。私が試してきました:

find . -name *.xml -exec grep -li "string1\|string2" {} \; | xargs grep -Li "string3\|string4"

しかし、findから返されるファイル名には名前にスペースが含まれており、2番目のgrepがそれらをすべて小さなチャンクに分割し、もちろんそのようなファイルを見つけられないため、問題があります。xargsに追加しようとし-0ましたが、エラーは削除されましたが、「ファイル名が長すぎます」と表示され、最初のgrepのみが実行されます。

名前にスペースが含まれるファイルで適切に動作するようにこのコマンドを調整するにはどうすればよいですか?


これはスーパーユーザーのものではありませんか?

2
bashスクリプトは、プログラミング関連とシステムメンテナンス関連の両方であるため、どちらのサイトにも属していると思います。
aioobe

1
現時点では、UNIXボックス上で、私は(GNU grepのを仮定して)推測すると思いません、あなたのような何かを試みることができるfind . -name "*.xml" -exec grep -liZ "string1\|string2" {} \; | xargs -0 grep -Li "string3\|string4"Zこのフラグへgrepと互換性があり、その結果リスト上のゼロターミネータを、出力xargs -0
マット・ギブソン

@pilcrow -print0は最初のgrepに一致するファイル名だけを選択するのではなく、ファイル名を出力するだけなので、この状況ではまったく機能しません。パイプを通過する最初のgrepの出力です。そのため、-Zフラグが必要なのだと思います。でも、箱なしで遊ぶのは難しい:)
マットギブソン

@Matt、はい、それを行う方法は複数あります。:)
巡礼

回答:


3

それを行うには複数の方法があります。これにより、実行されるプロセスの総数が最小限に抑えられます。

find . -name \*.xml -print0          \   # List of *.xml files (NUL-terminated)
  | xargs -0 grep -Zli 'string[12]'  \   # is input to first grep, which sends (NUL-term'd)
  | xargs -0 grep -Li  'string[34]'      # file list to second grep

GNU grepへのフラグを思い出させてくれたMatt Gibsonに感謝-Zします。


はい、それは良い方法です。@Cicerone-また、@ pilcrowと私はどちらも*.xml、シェルの拡張を避けるために何らかの方法でエスケープする必要があると想定していることに注意してください。
マットギブソン

これも機能し、非常に高速です!

3

findファイル名のスペースに関するすべての問題を回避するために、すべてを1つにできます。何かのようなもの

find . -exec grep -liq "string1\|string2" {} \; -not -exec grep -liq "string3\|string4" {} \; -print

「-q」は、すべてのgrep出力を抑制します。-execそれが一致するものを見つけたときにはgrepがするように、プロセスは、0のステータスで終了したときに、主はtrueを返し、そして-not主はそれを逆にします。したがって、に2つの条件を直接配置findし、その結果、両方を満たすファイル名のみを出力します。パイプは不要です!


あなたの答えが現れたとき、私はちょうどこの詳細を練っていました。

すみません、@コリン。それが私に起こるとき、私は嫌い:)
アーネストフリードマンヒル

2番目のgrepが機能するときにファイルがディスクキャッシュに残っている可能性が高いソリューションの場合は+1。
オレ丹下

2

私のコメントで述べたように、あなたが行方不明になっているのは、grepあなたが試していた-0と一緒に行く最初の-Zフラグだけだと思いますxargs

find . -name "*.xml" -exec grep -liZ "string1\|string2" {} \; | xargs -0 grep -Li "string3\|string4"

0

制限要因がCPU(つまり、ディスクが高速)であり、CPUコアが多い場合、GNU Parallelを使用できます。

find . -type f| parallel grep -Lq foo {} '||' grep -l bar {}

grepすぐに2つのsを実行することにより、ファイルがまだディスクキャッシュにある可能性があります。ディスクシークが遅い場合、追加-j1して並列処理を無効にすることができます。

詳細については、紹介ビデオをご覧くださいhttp : //www.youtube.com/watch?v=OpaiGYxkSuQ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.