web-dev-qa-db-ja.com

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

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

    for file in `find . -name "*.py"`; do echo $file; grep something $file; done
17
Gang
find . -name '*.py' -exec grep something {} \; -print

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

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

一致するすべての行の前にファイル名を出力します(/dev/null一致するファイルがoneしかない場合grepは、1つのファイルしか渡されない場合、ファイル名を出力しませんGNU grepの実装には-Hオプションを使用することもできます)。

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

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

一致する行の前にファイル名beforeを出力するには、代わりに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とその派生物でも動作します)。

25

GNU grepを使用している場合は、その-rまたは--recursiveこの簡単な検索を行うオプション:

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

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

6
Toby Speight

ファイル名を出力に含めるように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
5
rollstuhlfahrer

使用 -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
kmkaplan

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) {
...

ここではお見せできませんが、出力はきれいに色分けされています。ファイル名はオリーブグリーンで、行番号はゴールドイエローで、各行の一致する部分はブラッドレッドで表示されます。色はカスタマイズ可能です。

1
JoL

あなたは次のようなことを試すことができます:

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

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

1
Romeo Ninov