見つかったパターンのみでファイル名を検索およびエコーします


15

私はこれをよく使いましたが、達成しようとする改善は、grepで一致しなかったエコーファイル名を避けることです。これを行うより良い方法は?

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

回答:


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

一致する行の後にファイル名を出力します。

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

我々は追加(すべての一致行の前にファイル名を印刷し/dev/nullだけありますケースのための1と一致するファイルは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
  }' {} +

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

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および派生物でも動作します)。


6

GNU grepを使用している場合は、その-ror --recursiveオプションを使用して、この単純な検索を実行できます。

grep -r --include '*.py' -le "$regexp" ./ # for filenames only
grep -r --include '*.py' -He "$regexp" ./ # for filenames on each match

findより高度な述語が必要な場合にのみ必要です。


1
GNUのバージョンによってgrepgrepまたはディレクトリへのシンボリックリンクやトラバースシンボリックリンクの内側に見えない場合があります。また、他の種類の非正規ファイルの処理にはいくつかのバリエーションがあります。
ステファンシャゼラス

5

出力にファイル名を含めるようにgrepに指示できます。そのため、一致する場合はコンソールに表示されます。ファイル内に一致するものがない場合、そのファイルの行は出力されません。

find . -name "*.py" | xargs grep -n -H something

からman grep

-H       Always print filename headers with output lines
-n, --line-number
         Each output line is preceded by its relative line number in the file, starting at line 1.  The line number counter is reset for each file processed.
         This option is ignored if -c, -L, -l, or -q is specified.

ファイルに名前にスペースが含まれている場合は、NUL文字をセパレーターとして使用するようにパイプを切り替える必要があります。完全なコマンドは次のようになります。

find . -name "*.py" -print0 | xargs -0 grep -n -H something

1

次のようなものを試すことができます:

find . -name "*.py:" -exec grep -l {} \;

findコマンドとその標準のfindコマンド機能によって検出された、すべてのファイルに対するこのexec grepコマンド


1

-l引数を使用します。

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

より見つけやすい使用法は次のとおりです。

for file in $(find . -name '*.py' -exec grep -l something '{}' +); do echo "$file"; grep something $file; done

1

grepデフォルトでは、希望する形式で結果を出力する代替手段があります。私が知っている2つの最も人気のあるものはag(別名「銀のサーチャー」)とackです。agはのより高速な代替手段として宣伝されていますack

$ ag '^\w+\s*\w+\(' ~/build/i3/src
build/i3/src/display_version.c
58:void display_running_version(void) {

build/i3/src/load_layout.c
42:static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings =
518:json_content_t json_determine_content(const char *filename) {
575:void tree_append_json(Con *con, const char *filename, char **errormsg) {

build/i3/src/x.c
64:CIRCLEQ_HEAD(state_head, con_state) state_head =
67:CIRCLEQ_HEAD(old_state_head, con_state) old_state_head =
70:TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head =
97:void x_con_init(Con *con, uint16_t depth) {
...

ここでは表示できませんが、出力はきれいに色付けされています。ファイル名はオリーブグリーン、行番号は金黄色、各行の一致した部分は赤で表示されます。ただし、色はカスタマイズ可能です。

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