To nie działa. Czy można to zrobić w find? Czy muszę xargs?Jak dołączyć rurę | w poleceniu linux find -exec?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
To nie działa. Czy można to zrobić w find? Czy muszę xargs?Jak dołączyć rurę | w poleceniu linux find -exec?
find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;
Zadanie interpretacji kreską jako instrukcja do uruchomienia wielu procesów i rury wyjście jednego procesu na wejście inny proces to odpowiedzialność powłoki (/ bin/sh lub odpowiednik).
W przykładzie można albo zdecydować się na korzystanie z górną powłokę poziom wykonać orurowanie tak:
find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'
Pod względem wydajności wynika to koszty jednorazowe wywołanie znaleźć liczne inwokacje o zcat, a jeden inwokacja agrep.
Spowoduje to utworzenie tylko jednego procesu agrep, który przetwarzałby wszystkie dane wyjściowe wygenerowane przez liczne wywołania zcat.
Jeśli chcesz z jakiegoś powodu chciał powołać agrep wiele razy, można zrobić:
find . -name 'file_*' -follow -type f \
-printf "zcat %p | agrep -dEOE 'grep'\n" | sh
ten konstruuje listę poleceń z użyciem rur do wykonania, a następnie wysyła je do nowej powłoce, aby rzeczywiście być wykonywane . (Pominięcie ostatecznego "| sh" jest dobrym sposobem na debugowanie lub wykonywanie suchych przebiegów linii poleceń takich jak ta.)
Pod względem wydajności ten wynik kosztuje jedno wywołanie znalezienia, jedno wywołanie sh, liczne wywołania zcat i liczne inwokacje agrep.
Najbardziej efektywnym rozwiązaniem pod względem liczby wywołań polecenia jest sugestia od Pawła Tomblin:
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
... który kosztuje jedno wywołanie znaleźć, jedno wywołanie xargs, kilka wezwań o zcat i jedno wezwanie agrep.
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
Mając nadzieję na uniknięcie -Print i xargs ze względów wydajności. Może to jest mój problem: find nie może obsłużyć wypisanych poleceń przez -exec – someguy
Nie działa to w przypadku plików z spacjami w ich nazwach; naprawić, zamień -print z -print0 i dodaj opcję -0 do xargs –
@someguy - Wha? Unikanie xargs ze względów wydajnościowych? Wywołanie jednej instancji zcat i przekazanie jej listy wielu plików jest * znacznie * wydajniejsze niż wykonanie nowej instancji dla każdego znalezionego pliku. –
rozwiązanie jest proste: wykonać przez sh
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;
To, co OP próbował osiągnąć, można spotkać z powyższymi sugestiami, ale to właśnie on odpowiada na zadane pytanie. Istnieją powody, aby zrobić to w ten sposób - exec jest o wiele potężniejszy niż działanie na plikach zwracanych przez find, szczególnie w połączeniu z testem. Na przykład: znajdź geda-gaf/typ d -exec bash -c 'DIR = {}; [[$ (znajdź $ DIR -maxdepth 1 | xargs grep -i spice | wc -l) -ge 5]] && echo $ DIR '\; Zwróci wszystkie katalogi w ścieżce wyszukiwania, które zawierają więcej niż 5 wierszy łącznie spośród wszystkich plików w tym katalogu zawierających słowo spice. – swarfrat
Najlepsza odpowiedź. Pomijanie całego wyniku (jak sugerują inne odpowiedzi) nie jest tym samym, co grep dla każdego pliku. Wskazówka: zamiast sh możesz użyć dowolnej innej powłoki (próbowałem tego z bash i działa poprawnie). – pagliuca
Upewnij się, że nie przeoczyłeś opcji '-c'. W przeciwnym razie pojawi się zagadkowy komunikat o błędzie "Brak takiego pliku lub katalogu". – asmaier
Można również podłączyć do pętli while
, która może wykonywać wiele operacji na pliku znajdującym się pod adresem find
. Więc tutaj jest jeden dla patrząc w jar
archiwum dla danego pliku klasy java w folderze z dużej dystrybucji w jar
plików
find /usr/lib/eclipse/plugins -type f -name \*.jar | while read jar; do echo $jar; jar tf $jar | fgrep IObservableList ; done
kluczowym punktem jest, że pętla while
zawiera wiele poleceń odwołujące przekazany w nazwie pliku oddzielone średnik i te polecenia mogą zawierać potoki. Tak więc w tym przykładzie wywołuję echo nazwy pasującego pliku, a następnie wyświetlam zawartość filtrowania archiwum dla danej nazwy klasy. Wyjście wygląda następująco:
/usr/lib/eclipse/plugins/org.eclipse.core.contenttype.source_3.4.1.R35x_v20090826-0451.jar /usr/lib/eclipse/plugins/org.eclipse.core .databinding.observable_1.2.0.M20090902-0800.jar org/eclipse/core/databinding/obserserv/list/IObservableList .class /usr/lib/eclipse/plugins/org.eclipse.search.source_3.5.1. r351_v20090708-0800.jar /usr/lib/eclipse/plugins/org.eclipse.jdt.apt.core.source_3.3.202.R35x_v20091130-2300.jar /usr/lib/eclipse/plugins/org.eclipse.cvs.source_1.0.400.v201002111343.jar /usr/lib/eclipse/plugins/org.eclipse.help.appserver_3.1.400.v20090429_1800.jar
w mojej powłoce bash (xubuntu10.04/xfce) tak naprawdę czyni dopasowaną nazwę klasy pogrubioną, ponieważ fgrep
podświetla dopasowany ciąg; dzięki temu można z łatwością zeskanować listę setek znalezionych plików jar
i łatwo zobaczyć wszystkie dopasowania.
na oknach można zrobić to samo z:
for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList
Zauważ, że w oknach, które na polecenie jest separator „&” nie „;” i że '@' tłumi echo polecenia, aby dać czysty wynik, tak jak wynik linuksa znajdujący się powyżej; chociaż findstr
nie jest pogrubionym pasującym ciągiem, więc musisz przyjrzeć się bliżej wynikowi, aby zobaczyć dopasowaną nazwę klasy. Okazuje się, że okna „dla” polecenia wie sporo sztuczek, takich jak zapętlenie poprzez pliki tekstowe ...
cieszyć
Kolejną zaletą xargs byłoby to, że można go przyspieszyć nowoczesnym procesorem wielordzeniowym jeszcze bardziej, używając przełącznika -P (-P 0). – flolo
Tak, opcja -P jest rzeczywiście dobrym sposobem na przyspieszenie wykonywania w ogóle. Niestety, istnieje ryzyko, że wynik równoległych procesów zcat zostanie podłączony do przeplecionego agrepu, co wpłynie na wynik. Efekt ten można wykazać za pomocą: echo -e "1 \ n2" | xargs -P 0 -n 1 tak | uniq –
@Adam, wprowadziłem sugerowaną zmianę. –