Robię finda następnie otrzymuję listę plików. Jak przesłać potokiem do innego narzędzia, takiego jak cat(aby cat wyświetlał zawartość wszystkich tych plików) i zasadniczo potrzebował grepczegoś z tych plików.
Robię finda następnie otrzymuję listę plików. Jak przesłać potokiem do innego narzędzia, takiego jak cat(aby cat wyświetlał zawartość wszystkich tych plików) i zasadniczo potrzebował grepczegoś z tych plików.
Odpowiedzi:
Przesyłanie potokowe do innego procesu (chociaż to NIE osiągnie tego, o czym mówiłeś, że próbujesz zrobić):
command1 | command2
Spowoduje to wysłanie danych wyjściowych polecenia 1 jako danych wejściowych polecenia 2
-execna find(to zrobi to, co chcesz zrobić - ale jest specyficzne dla find)
find . -name '*.foo' -exec cat {} \;
(Wszystko pomiędzy findi -execsą predykatami znajdowania, których już używałeś. {}Zastąpi konkretny plik znaleziony w poleceniu ( cat {}w tym przypadku); \;ma to zakończyć -execpolecenie).
wysyła dane wyjściowe jednego procesu jako argumenty wiersza poleceń do innego procesu
command2 `command1`
na przykład:
cat `find . -name '*.foo' -print`
(Zauważ, że są to TYLNE CYTATY, a nie regularne cudzysłowy (pod tyldą ~ na mojej klawiaturze).) Spowoduje to wysłanie wyniku command1do command2jako argumentów wiersza poleceń. Pamiętaj jednak, że nazwy plików zawierające spacje (znaki nowej linii itp.) Zostaną podzielone na osobne argumenty.
findpozwalają pisać:, find . -name '*.foo' -exec cat {} +gdzie +wskazuje, że findpowinno grupować tyle wygodnych nazw plików w jedno wywołanie polecenia. Jest to bardzo przydatne (zajmuje się spacjami itp. W nazwach plików bez uciekania się do -print0i xargs -0).
find . -name '*.foo' | xargs cat
find . -name '*.foo' | xargs cat | grep string
POSIX 2008 dodał +znacznik, findco oznacza, że teraz automatycznie grupuje tyle plików, ile jest to rozsądne, w wykonanie jednego polecenia, podobnie jak xargsrobi, ale ma wiele zalet:
Problem z nazwą pliku jest problemem xargsbez -0opcji, a problem „uruchom nawet przy zerowych nazwach plików” jest problemem z -0opcją lub bez - ale GNU xargsma opcję -rlub --no-run-if-empty, aby temu zapobiec. Ponadto notacja ta ogranicza liczbę procesów, nie dlatego, że prawdopodobnie zmierzysz różnicę wydajności. Dlatego można rozsądnie napisać:
find . -exec grep something {} +
find . -print | xargs grep something
Jeśli jesteś na Linuksie lub mają GNU findi xargspoleceń, a następnie skorzystać -print0z finda -0z xargsw nazwach plików uchwyt zawierających spacje i inne znaki odd-ball.
find . -print0 | xargs -0 grep something
grepJeśli nie chcesz nazw plików (tylko tekstu), dodaj odpowiednią opcję grep(zwykle w -hcelu pominięcia „nagłówków”). Aby absolutnie zagwarantować, że nazwa pliku jest drukowana przez grep(nawet jeśli znaleziono tylko jeden plik lub ostatnie wywołanie grepma tylko 1 nazwę pliku), następnie dodaj /dev/nulldo xargswiersza poleceń, aby zawsze były co najmniej dwie nazwy plików.
xargs grep something.
findjest przesyłane do standardowego wejścia xargs. xargsProgram odczytuje swoje standardowe wejście, dzieląc wejście w białej przestrzeni (spacje, znaki nowej linii, zakładki, itp) i dodaje kilka słów do komendy grep somethingi wykonuje wiersza poleceń. xargsnastępnie kontynuuje czytanie danych wejściowych i wykonywanie poleceń, dopóki nie zabraknie danych wejściowych. xargsuruchamia greppolecenie tak często, jak jest to konieczne dla danych wejściowych, które zostały podane (z findtego przykładu).
/dev/nullutraty komunikatów o błędach.
Istnieje kilka sposobów przekazywania listy plików zwróconych przez findpolecenie do catpolecenia, chociaż technicznie nie wszystkie z nich używają potokowania i żaden z nich nie jest bezpośrednio potokowany bezpośrednio cat.
Najprostszym jest użycie backticks ( `):
cat `find [whatever]`
To pobiera dane wyjściowe findi skutecznie umieszcza je w wierszu poleceń cat. Nie działa to dobrze, jeśli findma zbyt dużo danych wyjściowych (więcej niż może zmieścić się w wierszu poleceń) lub jeśli dane wyjściowe zawierają znaki specjalne (takie jak spacje).
W niektórych powłokach, w tym bash, można użyć $()zamiast backticks:
cat $(find [whatever])
Jest to mniej przenośne, ale można je zagnieździć. Poza tym ma prawie takie same zastrzeżenia jak backtyki.
Ponieważ uruchamianie innych poleceń na tym, co znaleziono, jest powszechnym zastosowaniem find, find ma -execakcję, która wykonuje polecenie dla każdego znalezionego pliku:
find [whatever] -exec cat {} \;
{}Jest symbolem zastępczym dla nazwy pliku, a \;znaki końca polecenia (jest to możliwe, aby po inne działania -exec).
Będzie on uruchamiany catraz dla każdego pliku, zamiast uruchamiać jedną instancję, catprzekazując mu wiele nazw plików, co może być nieefektywne i może nie mieć pożądanego zachowania w przypadku niektórych poleceń (choć jest w porządku cat). Składnia jest również niewygodna w pisaniu - musisz uciec od średnika, ponieważ średnik jest szczególny dla powłoki!
Niektóre wersje find(zwłaszcza w wersji GNU) pozwalają zastąpić ;z +do użytku -execów trybie dopisywania do uruchomienia mniej przypadków” cat:
find [whatever] -exec cat {} +
Spowoduje to przekazanie wielu nazw plików do każdego wywołania cat, co może być bardziej wydajne.
Pamiętaj jednak, że nie można zagwarantować użycia pojedynczego wywołania. Jeśli linia poleceń byłaby zbyt długa, argumenty byłyby rozłożone na wiele wywołań cat. Na catto chyba nie jest to nic wielkiego, ale dla niektórych innych poleceń może się to zmienić zachowanie w niepożądany sposób. W systemach Linux limit długości wiersza poleceń jest dość duży, więc podział na wiele wywołań jest dość rzadki w porównaniu do niektórych innych systemów operacyjnych.
Klasyczne / przenośne podejście polega na użyciu xargs:
find [whatever] | xargs cat
xargsuruchamia podane polecenie ( catw tym przypadku) i dodaje argumenty na podstawie tego, co czyta ze standardowego wejścia. Podobnie jak w -execprzypadku +, w razie potrzeby spowoduje to uszkodzenie wiersza poleceń. Oznacza to, że jeśli findwytworzy zbyt dużo danych wyjściowych, będzie działać catwiele razy. Jak wspomniano we -execwcześniejszej części, istnieje kilka poleceń, w których podział może powodować różne zachowania. Zauważ, że użycie xargstego typu powoduje problemy ze spacjami w nazwach plików, ponieważ xargsużywa tylko białych znaków jako separatora.
Najbardziej niezawodna, przenośna i wydajna metoda wykorzystuje również xargs:
find [whatever] -print0 | xargs -0 cat
-print0Flaga mówi findużywać \0(znak null) separatory pomiędzy nazwami plików, a -0flaga mówi xargssię spodziewać tych \0ograniczników. To zachowanie jest prawie identyczne jak w podejściu -exec... +, ale jest bardziej przenośne (ale niestety bardziej szczegółowe).
ls.
$()Działa również z poleceniami innymi niż find .
Brzmi jak praca dla skryptu powłoki:
for file in 'find -name *.xml'
do
grep 'hello' file
done
czy jakoś tak
Polecenie find ma argument -exec, którego możesz użyć do takich rzeczy, możesz po prostu wykonać grep bezpośrednio za jego pomocą.
Na przykład ( stąd inne dobre przykłady na tej stronie ):
find . -exec grep "www.athabasca" '{}' \; -print
W bash odpowiednie będą:
find /dir -type f -print0 | xargs -0i cat {} | grep whatever
To znajdzie wszystkie pliki w /dirkatalogu i bezpiecznie potokuje nazwy plików xargs, które bezpiecznie będą prowadzić grep.
Pomijanie xargsnie jest dobrym pomysłem, jeśli masz wiele tysięcy plików /dir; catulegnie awarii z powodu nadmiernej długości listy argumentów. xargszałatwi to dla ciebie.
-print0Argument findzazębia się z -0argumentem, aby xargsprawidłowo obsługiwać nazwy plików ze spacjami. -iArgument xargspozwala wstawić nazwę pliku, gdzie wymagane w catwierszu poleceń. Nawiasy zastępuje się nazwą pliku wprowadzoną do catpolecenia z find.
To działa dla mnie
find _CACHE_* | while read line; do
cat "$line" | grep "something"
done
Spowoduje to wydrukowanie rekursywnie nazwy i zawartości tylko plików.
find . -type f -printf '\n\n%p:\n' -exec cat {} \;
Edycja (ulepszona wersja): Spowoduje to wydrukowanie rekursywnie nazwy i zawartości plików tekstowych (ascii).
find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'
Jeszcze jedna próba
find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;
Czy próbujesz znaleźć tekst w plikach? Możesz po prostu użyć do tego grep ...
grep searchterm *
Aby wyświetlić i zobaczyć zawartość wszystkich plików abc.def na serwerze w katalogach / ghi i / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;
Aby wyświetlić listę plików abc.def, które skomentowały wpisy i wyświetlić, zobacz te wpisy w katalogach / ghi i / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
find -name '*.foo' -printpracował dla mnie świetnie ... Dzięki