Polecenia potokowe po potoku xargs

38

HP-UX ***** B.11.23 U ia64 **** licencja nieograniczonego użytkownika

find . -type d -name *log* | xargs ls -la

daje mi nazwy katalogów (te, które zawierają lognazwę katalogu), a następnie wszystkie pliki w tym katalogu.

Katalogi  /var/opt/SID/application_a/log/,  /var/opt/SID/application_b/log/,  /var/opt/SID/application_c/log/i tak dalej zawierać pliki dziennika.

Chcę, aby polecenie zawierało tylko dwa najnowsze pliki dziennika ls, których zwykle używam ls -latr | tail -2.

Wynik musi być mniej więcej taki ...

/var/opt/SID/application_a/log/
-rw-rw-rw-   1 user1    user1      59698 Jun 11  2013 log1
-rw-rw-rw-   1 user1    user1      59698 Jun 10  2013 log2
/var/opt/SID/application_b/log/
-rw-rw-rw-   1 user1    user1      59698 Jun 11  2013 log1
-rw-rw-rw-   1 user1    user1      59698 Jun 10  2013 log2
/var/opt/SID/application_c/log/
-rw-rw-rw-   1 user1    user1      59698 Jun 11  2013 log1
-rw-rw-rw-   1 user1    user1      59698 Jun 10  2013 log2

find . -type d -name *log* | xargs ls -la | tail -2nie daje mi powyższego wyniku. Dostaję listę ostatnich dwóch plików find . -type d -name *log* | xargs ls -lapoleceń.

Czy mogę przesyłać polecenia po potoku xargs? Jak inaczej zapytać, aby uzyskać wynikową listę plików w powyższym formacie?

find . -type d -name *log* | xargs sh -c "ls -ltr | tail -10"

daje mi listę dziesięciu nazw katalogów w bieżącym katalogu, który akurat jest /var/opt/SIDi nie jest to również to, czego chcę.

inna osoba 1
źródło
2
Powinieneś zacytować, w *log*przeciwnym razie powłoka go rozszerzy.
Anthon
Pamiętaj, że sh -cspodziewa się , że nazwa polecenia (parametr 0) będzie drugim argumentem, więc powinieneś zawsze to robić find . -type d -name *log* | xargs sh -c "ls -ltr | tail -10" lstail(zwróć uwagę lstailna końcu, który będzie służył jak $0dla utworzonej powłoki). W przeciwnym razie pierwszy z wyników wypełni tę rolę i pozostanie niewykorzystany.
Jonas

Odpowiedzi:

57

Jesteś prawie na miejscu. W swoim ostatnim poleceniu możesz użyć, -Iaby wykonać lspoprawnie

-I replace-str

    Zamień wystąpienie replace-str w argumentach początkowych na nazwy odczytane ze standardowego wejścia. Ponadto, niecytowane puste miejsca nie kończą elementów wejściowych; zamiast tego separatorem jest znak nowej linii. Implikuje -xi -L 1.

Więc z

find . -type d -name "*log*" | xargs -I {} sh -c "echo {}; ls -la {} | tail -2"

znajdziesz echokatalog znaleziony przez find, a następnie zrób ls | tailto.

fredtantini
źródło
odnaleźć . -type d -name " log " | xargs -I {} sh -c "echo {}; ls -ltr {} | grep -E \" file_in | file_out \ "| tail -5" Użyłem tego.
anotherperson1
3
Robię zxargs -n 1 sh -c 'echo $0'
Ginhing,
1
na macOS zamiana nie działała w cytowanym poleceniu, więc echo $0była pomocna (i bardziej zrozumiała)
mpuncel,
1
Aby pracować z nazwami plików ze spacjami, wykorzystania -print0, xargs -0i uciec {}w cudzysłów wewnątrz tej shkomendy:find . -type d -name "*log*" -print0 | xargs -0 -I {} sh -c "echo \"{}\";ls -la \"{}\" | tail -2"
Benedikt Köppel
Używam „xargs -n 1 sh -c” echo \ $ 0 | $ func "` `jeśli muszę użyć zmiennej $ func
bóg
5

GNU Parallel sprawia, że ​​tego rodzaju zadania są łatwe:

find . -type d -name "*log*" | parallel --tag "ls -la {} | tail -2"

Jeśli nie chcesz wykonywać pełnej instalacji GNU Parallel, możesz wykonać minimalną instalację: http://git.savannah.gnu.org/cgit/parallel.git/tree/README

Ole Tange
źródło
2

Oprócz fredtantini i jako ogólne wyjaśnienie (ponieważ dokumenty są nieco mylące):

xargs -I {}Podejmie „{}” znaki ze standardowego wejścia i zastąpić je cokolwiek pochodzi z rury. Oznacza to, że możesz faktycznie zastąpić {}dowolną kombinacją znaków (być może w celu lepszego dopasowania preferowanego smaku programowania). Na przykład : xargs -I % sh -c "echo %". Jeśli zawsze używasz xargs -I {}, możesz go zastąpić, xargs -iponieważ jest to skrót.

Polecenie sh -cbash / shell odczyta następne polecenie z łańcucha, a nie ze standardowego wejścia. Więc pisanie sh -c "echo something"jest równoważne echo something.

xargs -I {} sh -c "echo {}"Odczyta wejście utworzony z sh -cco jest echo {}. Ponieważ powiedziałeś, aby zastąpić {}argumentami, które otrzymałeś z potoku, tak się stanie.

Możesz to łatwo przetestować nawet bez instalacji potokowej, po prostu wpisz powyższe polecenie w terminalu. Cokolwiek napiszesz później, zostanie wyświetlone na terminalu (Ctrl-D, aby wyjść).

W ls -la {}poleceniu to samo dzieje się ponownie. {}Otrzymuje z treści polecenia wstępnego rury.

Borisu
źródło