パターンが見つかったファイル名のみを検索してエコーします。

パターンが見つかったファイル名のみを検索してエコーします。

私はこれを大量に使用し、私が達成しようとする改善は、grepで一致しないファイル名がエコーされるのを防ぐことです。これを行うためのより良い方法は何ですか?

    for file in `find . -name "*.py"`; do echo $file; grep something $file; done

ベストアンサー1

find . -name '*.py' -exec grep something {} \; -print

ファイル名を印刷します後ろに一致する行。

find . -name '*.py' -exec grep something /dev/null {} +

一致する各行の前にファイル名を印刷します(/dev/null私たちが追加した場合は一つ検索するファイルのみを渡す場合、file asと一致するとgrepファイル名は印刷されません。 GNU実装には代替オプションがgrepあります-H

find . -name '*.py' -exec grep -l something {} +

少なくとも1つの一致する行を持つファイルのファイル名のみを印刷します。

ファイル名の印刷今後行を一致させるには、代わりにawkを使用できます。

find . -name '*.py' -exec awk '
  FNR == 1 {filename_printed = 0}
  /something/ {
    if (!filename_printed) {
      print FILENAME
      filename_printed = 1
    }
    print
  }' {} +

または、各ファイルに対して2回呼び出します。各ファイルに対して少なくとも1つのコマンドと最大2つのコマンドをgrep実行し、ファイルの内容を2回読み取ると効率が低下します。grep

find . -name '*.py' -exec grep -l something {} \; \
                    -exec grep something {} \;

いずれにせよ、findそのように出力を繰り返したくありません。そして変数を引用することを忘れないでください

GNU ツールでシェルループを使用するには:

find . -name '*.py' -exec grep -l --null something {} + |
   xargs -r0 sh -c '
     for file do
       printf "%s\n" "$file"
       grep something < "$file"
     done' sh

(FreeBSDおよびその派生物にも適用されます)。

おすすめ記事