Próbuję uruchomić grep na liście kilkuset plików:
$ head -n 3 <(cat files.txt)
admin.php
ajax/accept.php
ajax/add_note.php
Jednak pomimo tego, że szukam ciągu, o którym wiem, że znajduje się w plikach, następujące pliki nie wyszukują plików:
$ grep -i 'foo' <(cat files.txt)
$ grep -i 'foo' admin.php
The foo was found
Znam -f
flagę, która odczytuje wzorce z pliku. Ale jak czytać pliki wejściowe ?
Rozważyłem straszne obejście kopiowania plików do katalogu tymczasowego, ponieważ cp
wydaje się, że obsługuje ten <(cat files.txt)
format, i stamtąd grepowanie plików. Shirley jest lepszy sposób.
źródło
while
można otrzymać linie file.txt jako takie.while
nie odbiera dokładnie wierszy z pliku,read
robi to;while
pozwala nam to zrobić tylko w pętli. Pętla kończy się, gdy kończy sięread
niepowodzeniem (tzn. Zwraca niezerowy kod powrotu), zwykle z powodu osiągnięcia końca pliku.IFS= read -r filename
,read filename
to coś innego.-H
jest to rozszerzenie GNU. Tracisz trochę--
.zakładając, że pliki są puste lub rozdzielane znakami nowej linii (gdzie można użyć cudzysłowów lub ukośników odwrotnych do tych separatorów). W GNU
xargs
możesz określić ogranicznik za pomocą-d
(który następnie wyłącza obsługę cytowania).zakładając, że pliki są oddzielone spacją, tabulatorem lub znakiem nowej linii (nie ma możliwości ucieczki przed nimi, chociaż można wybrać inny separator, przypisując go
IFS
). Ten nie powiedzie się, jeśli lista plików jest zbyt duża w większości systemów.Zakładają również, że żaden plik nie jest wywoływany
-
.źródło
$(< file)
zamiast$(cat file)
, przynajmniej wbash
izsh
.Aby odczytać listę nazw plików ze standardowego wejścia, możesz użyć
xargs
. Na przykład,Domyślnie
xargs
odczytuje elementy ze standardowego wejścia, rozdzielane spacjami.-d'\n'
Informuje go używać nowej linii jako separatora argumentów, więc może obsługiwać nazwy plików zawierające spacje. (Jak zauważa Stéphane Chazelas, jest to rozszerzenie GNU). Jednak nie poradzi sobie z nazwami plików zawierającymi znaki nowej linii; potrzebowalibyśmy nieco bardziej skomplikowanego podejścia, aby sobie z nimi poradzić.FWIW, takie podejście jest nieco szybsze niż
while read
pętla, ponieważread
polecenie bash jest bardzo wolne - odczytuje dane znak po znaku, podczas gdyxargs
bardziej efektywnie odczytuje dane wejściowe. Ponadtoxargs
wywołujegrep
polecenie tylko tyle razy, ile potrzeba, a każde wywołanie otrzymuje wiele nazw plików, a to jest bardziej wydajne niż wywoływaniegrep
pojedynczo dla każdej nazwy pliku.Zobacz stronę manuala xargs i stronę informacyjną xargs, aby uzyskać dodatkowe informacje.
źródło
xargs
może czytać elementy z pliku (np. zfiles.txt
listy) za pomocą tej opcji:To też powinno działać:
lub dla spacji w nazwach plików
źródło
Możesz także zrobić za, ale przykład Oriona jest najprostszy:
(Dla każdego pliku wymienionego w pliku.txt wykonaj na nim polecenie grep.)
źródło