Отображение имени файла перед соответствующей строкой

282

Как я могу grepотобразить имя файла перед соответствующими строками в его выводе?

Вивек
источник
2
Пожалуйста, скажите свою версию grepgrep --version
Кент
3
kent, grep --versionэто команда, используемая для определения версии grep? Если так, это не работает. Не удалось найти другую команду, чтобы узнать версию grep.
Вивек
2
хороший вопрос, но 'Os version' - это запутанный пример имени файла
HaveAGuess
1
ОС и версия здесь не имеет значения.
MD XF
grep 'pattern' *
user0

Ответы:

431

Попробуйте этот маленький трюк, чтобы убедить себя grepв том, что он имеет дело с несколькими файлами, и отобразить имя файла:

grep 'pattern' file /dev/null

Чтобы также получить номер строки:

grep -n 'pattern' file /dev/null
Scrutinizer
источник
6
Да, это сработало. Подскажите, пожалуйста, в чем смысл добавления /dev/nullэтой команды?
Вивек
55
Если grepуказано несколько имен файлов, он будет автоматически отображать имена файлов перед совпадением, но не будет указывать имя файла в случае одного входного файла. Используя /dev/nullв качестве дополнительного входного файла, grep«думает», что он имеет дело с несколькими файлами, но / dev / null, конечно, пуст, поэтому он не будет отображаться в списке совпадений ..
Scrutinizer
32
использование / dev / null - хитрый трюк, но я думаю, что предложение ниже флага -H - лучший ответ.
JohnQ
22
Хорошо, но -Hопция для grep не является частью POSIX, а используемая ОС - Solaris 10, где ни у стандартной, ни у POSIX-совместимой версии grep такой -Hопции нет.
Тщательный анализ
4
Это важно, если вы используете grep с find, например, find . -name foo -exec grep pattern {} \;при условии, что fooв вашем подкаталоге много файлов, названных по- findпрежнему , все равно grepпредоставляется один файл для работы за раз. /dev/nullТрюк , кажется, работает во всех Linux / OSX ароматы , которые я пробовал, так что престижность! Заметьте, я думаю, что -Hэто чище, но, как упоминалось ниже, оно может не поддерживаться вашей версией grep.
Джон V
297

Если у вас есть варианты -Hи -nдоступны ( man grepэто ваш друг):

$ cat file
foo
bar
foobar

$ grep -H foo file
file:foo
file:foobar

$ grep -Hn foo file
file:1:foo
file:3:foobar

Параметры:

-H, --with-filename

Напечатайте имя файла для каждого совпадения. Это значение по умолчанию, когда для поиска требуется более одного файла.

-n, --line-номер

Приставьте каждую строку вывода к номеру строки на основе 1 в своем входном файле. (-n определяется POSIX.)

-Hэто расширение GNU, но -nэто определяется POSIX

Крис Сеймур
источник
3
Нет, -Hздесь не поддерживается.
Вивек
1
Поддерживается, но всегда дает grep: file: Нет такого файла или каталога
pal4life
2
работает на Ubuntu -H и -n. Вероятно, со всеми более новыми версиями * nix
tgkprog
1
Я боролся с этим в течение многих лет без вечера, думая, что были эти варианты!
GreenSaguaro
46

Трюк не нужен.

grep --with-filename 'pattern' file

С номерами строк:

grep -n --with-filename 'pattern' file
MD XF
источник
3
@codeforester Я не знаю других grep, поэтому я не знаю.
MD XF
2
Прохладно ! это работало для Linux. Если вы используете Mac, можете установить coreutils с помощью brew. И не забудьте добавить PATH = "/ usr / local / opt / coreutils / libexec / gnubin: $ PATH" к
вашему
2
Это (также) работало в MinGW (я думаю, 1.0.17).
Питер Мортенсен
Это работает для меня со встроенным Mac grep (2.5.1-FreeBSD). Но использовать альтернативный Grep из Homebrew, другой способ для запуска , brew install grepа затем просто использовать ggrep. Нет необходимости изменять PATH.
wonderlr
5

Как насчет этого, чего мне удалось добиться, частично благодаря этому посту.

Вы хотите найти несколько файлов, скажем, журналы с разными именами, но с шаблоном (например filename=logfile.DATE), внутри нескольких каталогов с шаблоном (например /logsapp1, /logsapp2). У каждого файла есть шаблон, который вы хотите получить (например "init time"), и вы хотите иметь "init time"каждый файл, но зная, к какому файлу он принадлежит.

find ./logsapp* -name logfile* | xargs -I{} grep "init time" {} \dev\null | tee outputfilename.txt

Тогда outputfilename.txtбудет что-то вроде

./logsapp1/logfile.22102015: init time: 10ms
./logsapp1/logfile.21102015: init time: 15ms
./logsapp2/logfile.21102015: init time: 17ms
./logsapp2/logfile.22102015: init time: 11ms

В основном

find ./path_pattern/to_files* -name filename_pattern* | xargs -I{} grep "grep_pattern" {} \dev\null | tee outfilename.txt

Объяснение:

find Команда будет искать имена файлов на основе шаблона

затем труба xargs -I{}перенаправит findвывод на{}

который будет входом для grep ""pattern" {}

Тогда трюк, чтобы сделать grepотображение имен файлов\dev\null

и, наконец, записать вывод в файл с tee outputfile.txt

Это работало для меня в grepверсии 9.0.5, сборка 1989 года.

Lejuanjowski
источник
3
Или просто с помощью поискаfind ./path_pattern/to_files -type f -name "files*.log" -exec grep -Hn pattern {} \;
Мартин
1

Это небольшая модификация предыдущего решения. Мой пример ищет перенаправление stderr в скриптах bash: grep '2>' $(find . -name "*.bash")

Ричард Джессоп
источник
-7
grep 'search this' *.txt

работал для меня, чтобы искать через все файлы .txt (введите собственное значение поиска, конечно).

MagicMojo
источник