これを頻繁に使用しました。達成しようとしている改善点は、で一致しなかったエコーファイル名を回避することです。 grep。これを行うためのより良い方法は?
for file in `find . -name "*.py"`; do echo $file; grep something $file; done
コメント
- 関連( Ubuntuに質問):指定したディレクトリのファイル名でのみパターン/テキストを再帰的に検索しますか?
回答
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) { ...
ここでは表示できませんが、出力はきれいに色付けされています。ファイル名はオリーブグリーン、行番号はゴールドイエロー、各行の一致する部分は血の赤で表示されます。色はカスタマイズ可能です。