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

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

コメント

回答

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

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

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

一致するすべての行の前にファイル名を出力します( 1つしかない場合は/dev/nullを追加します grepとして一致するファイルは、検索するファイルが1つだけ渡された場合、ファイル名を出力しません。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および派生物でも機能します)。

回答

I 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が必要ですより高度な述語。

コメント

  • GNU grepのバージョンに応じて、grepは、シンボリックリンクの内部を調べたり、シンボリックリンクをディレクトリにトラバースしたりする場合としない場合があります。また、他の種類の非正規ファイルの処理にもいくつかのバリエーションがある場合があります。

回答

あなた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 

回答

次のようになります。次のようなものを試してください。

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

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

回答

-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 

回答

あります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) { ... 

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

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です