web-dev-qa-db-ja.com

検索を使用してファイルを取得した後にgrepを使用する

だから私はコマンドラインに比較的新しいです。特定の場所がないため、findを使用して複数のディレクトリから複数のファイルの出力を取得できました(これは短縮できると確信しています)。

find ./ -name filename1.ext && find ./ -name filename2.ext && find ./ -name filename3.ext

これで、必要なもののリストが表示されましたが、問題のファイルが見つかったので、情報を得るためにそれらをgrepしたいと思います。

4
trazinaz

すべてのnameプライマリを単一のfindステートメントにグループ化してから、find execute grepを実行できます。

find . \( -name filename1.ext -o \
      -name filename2.ext -o \
      -name filename3.ext \) \
      -exec grep 'pattern' {} \;
6
fd0

これを試して、

find ./ -type f \( -name filename1.ext -o -name filename2.ext -o -name filename3.ext \) -exec grep 'string' {} \;
  • -type fファイルを探しているため、結果をより早く取得するには、タイプを指定することをお勧めします。

  • -oはORを意味し、検索にファイル名を追加できます

3
Siva

正解の横に実際に-oおよび-exec、これは前のコマンドの出力をキャプチャして行ごとに解析する一般的な方法です

(find .... && find ... && cat ... && ls ... && ...) | while read line; do grep string $line; done
1
Jack

一般に、find + grepの組み合わせを行うには、少なくとも3つの方法があります。

  1. grepパターン`finddir検索指定子-print`
  2. finddirfind-specifiers-exec greppattern{} \;
  3. finddirfind-specifiers-print | xargs greppattern

そしてもちろん、ここでgrepについて特別なことは何もありません。これらと同じ3つのパターンをfindと任意のコマンドに使用できます。

ナンバー1は、ある意味で最も古く、最も基本的な方法です。なぜなら、逆引用符は常に、1つのコマンドの出力をキャプチャし、それを別のコマンドラインで使用する方法だからです。 (最近、バッククォートよりも優れた新しいバシズムがあり、すべてのクールな子供たちが使用しているという印象を受けますが、私は昔からのタイマーだと思います。)番号1の欠点は、find大量のファイルを検索すると、「コマンドラインが長すぎます」というエラーが発生する場合があります。

番号2は、find +コマンドの組み合わせを実行するためにfindに組み込まれた特別な機能です。それはそれでも問題ありませんが、2つの欠点があります。(1)見つかった各ファイルに対して補助コマンド(grepまたはその他)を再度呼び出すため、遅くなる可能性があります。(2)補助コマンドはgrepです。grepを呼び出すたびに1つのファイル名が表示されるため、一致するファイル名はリストされませんが、-exec grepを実行することで回避できます。 パターン{} /dev/null \;、または最近では、-exec grep -Hパターン{} \;

そして、3番目です。私の知る限り、xargsは最初の2つの制限を回避するために発明されました。 xargsは理論的には汎用プログラムですが、実際にはfindgrep以外のプログラムのペアで使用されることはほとんどないようです。 #1の欠点を完全に回避します。見つかったファイルの任意の数で動作します。それは効率的ですが、運が悪い場合は時々grepの最後の1つのファイル名を呼び出すため、/dev/nullまたは-Hトリックを引き続き使用する必要があります。そして、それ自体に欠点があります。見つかったファイル名のいずれかに空白が含まれていると機能しません。しかし、それを回避する方法もあります。

finddirfind-specifiers-print0 | xargs -0 greppattern

xargsがデフォルトで空白文字の代わりに入力で改行で区切られたファイル名を受け入れるように作成されていれば幸いですが、それは別の日の怒りです。)

0
Steve Summit

bashの使用:

shopt -s globstar
grep 'pattern' ./**/filename[123].ext

globstar Shellオプションを有効にすると、**パターンは*のように動作しますが、パス名の/全体で一致します。これは、パターンが数千のファイルと一致しない限り機能します。この場合、シェルから「引数リストが長すぎます」というエラーが発生する可能性があります。また、これは、find-type fテストで行うように、一致したパス名が通常のファイル用かどうかをチェックしません。また。パターンがanythingに一致しない場合、展開されません。

上記の3つの問題すべてを解決するループで:

shopt -s globstar
for pathname in ./**/filename[123].ext; do
    [ -f "$pathname" ] && grep 'pattern' /dev/null "$pathname"
done
0
Kusalananda