回答:
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および派生物でも動作します)。
GNU grepを使用している場合は、その-r
or --recursive
オプションを使用して、この単純な検索を実行できます。
grep -r --include '*.py' -le "$regexp" ./ # for filenames only
grep -r --include '*.py' -He "$regexp" ./ # for filenames on each match
find
より高度な述語が必要な場合にのみ必要です。
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
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) {
...
ここでは表示できませんが、出力はきれいに色付けされています。ファイル名はオリーブグリーン、行番号は金黄色、各行の一致した部分は赤で表示されます。ただし、色はカスタマイズ可能です。