Wyświetl nazwę pliku przed dopasowaniem linii

282

Jak mogę grepwyświetlić nazwę pliku przed pasującymi liniami w jego wynikach?

Vivek
źródło
2
proszę powiedz swoją wersję grepgrep --version
Kent
3
Kent, grep --versionczy to polecenie, którego należy użyć, aby poznać wersję grep? Jeśli tak, to nie działa. Nie można znaleźć żadnego innego polecenia, aby poznać wersję grep.
Vivek,
2
dobre pytanie, ale „wersja Os” to myląca przykładowa nazwa pliku
HaveAGuess
1
System operacyjny i wersja nie mają tu znaczenia.
MD XF
grep 'pattern' *
użytkownik0

Odpowiedzi:

430

Wypróbuj tę małą sztuczkę, aby grepprzekonać się, że ma do czynienia z wieloma plikami, aby wyświetlała nazwę pliku:

grep 'pattern' file /dev/null

Aby uzyskać także numer linii:

grep -n 'pattern' file /dev/null
Skrutator
źródło
6
Tak, zadziałało. Czy możesz mi powiedzieć, jakie znaczenie ma dodanie /dev/nulltego polecenia?
Vivek,
55
Jeśli grepjest dostarczany z wieloma nazwami plików, automatycznie wyświetli nazwy plików przed dopasowaniem, ale pozostawi nazwę pliku w przypadku pojedynczego pliku wejściowego. Używając /dev/nulljako dodatkowego pliku wejściowego grep„myśli”, że zajmuje się wieloma plikami, ale / dev / null jest oczywiście pusty, więc nie pojawi się na liście meczów.
Scrutinizer
32
użycie / dev / null to sprytna sztuczka, ale myślę, że lepsza odpowiedź to podana poniżej opcja -H.
JohnQ
22
OK, ale -Hopcja grep nie jest częścią POSIX, a używany system operacyjny to Solaris 10, w którym ani standardowa wersja grep, ani zgodna z POSIX wersja grep nie mają takiej -Hopcji.
Skrutinizer,
4
Jest to ważne, jeśli używasz grep z find, na przykład find . -name foo -exec grep pattern {} \;- zakładając, że foow katalogu znajduje się wiele plików o nazwie z podkatalogu, findnadal przekazujesz grepjeden plik do działania na raz. Ta /dev/nullsztuczka wydaje się działać we wszystkich wersjach linux / osx, których próbowałem, więc chwała! Uwaga: Myślę, że -Hjest to czystsze, ale jak wspomniano poniżej, może nie być obsługiwane przez twoją wersję grep.
Jon V
296

Jeśli masz dostępne opcje -Hi jest -ndostępny ( man grepjest twoim przyjacielem):

$ cat file
foo
bar
foobar

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

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

Opcje:

-H, - z nazwą pliku

Wydrukuj nazwę pliku dla każdego dopasowania. Jest to ustawienie domyślne, gdy istnieje więcej niż jeden plik do przeszukania.

-n, --line-number

Poprzedź każdą linię wyjścia numerem linii na podstawie 1 w swoim pliku wejściowym. (-n jest określone przez POSIX).

-Hjest rozszerzeniem GNU, ale -njest określone przez POSIX

Chris Seymour
źródło
3
Nie, -Htutaj nie jest obsługiwane.
Vivek,
1
Obsługiwane, ale zawsze daje grep: plik: Brak takiego pliku lub katalogu
pal4life
2
działa na Ubuntu -H i -n. Prawdopodobnie ze wszystkimi nowszymi wersjami * nix
tgkprog
1
Walczyłem z tym od lat bez wieczornego myślenia, że ​​są takie opcje!
GreenSaguaro
45

Żadna sztuczka nie jest konieczna.

grep --with-filename 'pattern' file

Z numerami linii:

grep -n --with-filename 'pattern' file
MD XF
źródło
3
@codeforester Nie znam żadnych innych grep, więc nie wiem.
MD XF,
2
Chłodny ! działało to w systemie Linux. jeśli używasz Maca, możesz zainstalować coreutils z naparami. I pamiętaj, aby dodać PATH = "/ usr / local / opt / coreutils / libexec / gnubin: $ PATH" do
swojego
2
To (także) działało w MinGW (1.0.17, jak sądzę).
Peter Mortensen,
Działa dla mnie z wbudowanym gre gre (2.5.1-FreeBSD). Ale aby użyć alternatywnego grep z Homebrew, innym sposobem jest uruchomienie, brew install grepa następnie użycie ggrep. Nie trzeba modyfikować ŚCIEŻKI.
wonderlr
5

Co powiesz na to, co udało mi się osiągnąć, częściowo dzięki temu postowi.

Chcesz znaleźć kilka plików, powiedzmy logi o różnych nazwach, ale wzorcu (np. filename=logfile.DATE), W kilku katalogach ze wzorcem (np /logsapp1, /logsapp2.). Każdy plik ma wzorzec, który chcesz grepować (np. "init time") I chcesz mieć "init time"każdy z nich, ale wiedząc, do którego pliku należy.

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

Wtedy outputfilename.txtbyłoby coś takiego

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

Ogólnie

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

Wyjaśnienie:

find polecenie przeszuka nazwy plików na podstawie wzorca

następnie potok xargs -I{}przekieruje dane findwyjściowe do pliku{}

który będzie wejściowy dla grep ""pattern" {}

Następnie sztuczka, aby grepwyświetlić nazwy plików\dev\null

i na koniec zapisz wynik w pliku za pomocą tee outputfile.txt

To działało dla mnie w grepwersji 9.0.5 kompilacji 1989.

Lejuanjowski
źródło
3
Lub po prostu użyj findfind ./path_pattern/to_files -type f -name "files*.log" -exec grep -Hn pattern {} \;
Martin
1

Jest to niewielka modyfikacja poprzedniego rozwiązania. Mój przykład szuka przekierowania stderr w skryptach bash: grep '2>' $(find . -name "*.bash")

Richard Jessop
źródło
-7
grep 'search this' *.txt

pracował dla mnie, aby przeszukać wszystkie pliki .txt (oczywiście wprowadź własną wartość wyszukiwania).

MagicMojo
źródło