Answers:
find . -name '*.py' -exec grep something {} \; -print
将在匹配的行后打印文件名。
find . -name '*.py' -exec grep something /dev/null {} +
会在每条匹配行的前面打印文件名(我们添加/dev/null
了一个匹配文件的情况,因为grep
如果只传递一个文件供查看,则不打印文件名。GNU实现为此grep
提供了一个-H
选项作为备选)。
find . -name '*.py' -exec grep -l something {} +
将仅打印具有至少一行匹配内容的文件的文件名。
要在匹配的行之前打印文件名,可以改用awk:
find . -name '*.py' -exec awk '
FNR == 1 {filename_printed = 0}
/something/ {
if (!filename_printed) {
print FILENAME
filename_printed = 1
}
print
}' {} +
或grep
为每个文件调用两次-尽管效率较低,因为它将至少运行一个grep
命令,每个文件最多运行两个命令(并读取文件内容两次):
find . -name '*.py' -exec grep -l something {} \; \
-exec grep something {} \;
无论如何,您都不想遍历find
like这样的输出,并记得引用您的variable。
如果要使用Shell循环,请使用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
或--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
您可以尝试类似:
find . -name "*.py:" -exec grep -l {} \;
该命令是每个文件的exec grep命令,由find命令及其标准的find命令功能发现
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) {
...
我无法在这里显示您的信息,但输出颜色整齐。我得到的文件名是橄榄绿色,行号是金黄色,每行中的匹配部分是血红色。颜色是可定制的。