Piping-Befehle nach einem gepipten Xargs

38

HP-UX ***** B.11.23 U ia64 **** Lizenz für unbegrenzte Benutzer

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

gibt mir die Verzeichnisnamen (die logim Verzeichnisnamen enthalten sind ), gefolgt von allen Dateien in diesem Verzeichnis.

Die Verzeichnisse  /var/opt/SID/application_a/log/,  /var/opt/SID/application_b/log/,  /var/opt/SID/application_c/log/usw. Protokolldateien enthalten.

Ich möchte, dass nur die zwei neuesten Protokolldateien vom lsBefehl aufgelistet werden , den ich normalerweise verwende ls -latr | tail -2.

Die Ausgabe muss ungefähr so ​​sein ..

/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 -2gibt mir das obige ergebnis nicht. Was ich bekomme, ist eine Liste der letzten beiden find . -type d -name *log* | xargs ls -laBefehlsdateien.

Kann ich also Befehle nach einer Pipe weiterleiten xargs? Wie frage ich sonst ab, um die resultierende Liste der Dateien im obigen Format zu erhalten?

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

gibt mir eine liste von zehn verzeichnisnamen innerhalb des aktuellen verzeichnisses was zufällig ist /var/opt/SIDund das ist auch nicht was ich will.

anotherperson1
quelle
2
Sie sollten das zitieren, *log*sonst wird die Shell es erweitern.
Anthon
Beachten Sie, sh -cdass der Befehlsname (Parameter 0) als zweites Argument erwartet wird. Dies sollten Sie immer tun find . -type d -name *log* | xargs sh -c "ls -ltr | tail -10" lstail(beachten Sie das lstailam Ende, das $0für die erstellte Shell verwendet wird). Andernfalls wird das erste Ihrer Ergebnisse diese Rolle ausfüllen und nicht verwendet.
Jonas

Antworten:

57

Du bist fast am Ziel. In Ihrem letzten Befehl können Sie verwenden -I, um das lsrichtig zu tun

-I replace-str

    Ersetzen Sie das Vorkommen von replace-str in den Anfangsargumenten durch Namen, die aus der Standardeingabe gelesen wurden. Außerdem werden Eingabeelemente nicht durch Leerzeichen in Anführungszeichen beendet. Stattdessen ist das Trennzeichen das Zeilenumbruchzeichen. Impliziert -xund -L 1.

Also mit

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

du wirst echodas dir durch finden find, dann mach das ls | taildrauf.

fredtantini
quelle
finden . -type d -name " log " | xargs -I {} sh -c "echo {}; ls -ltr {} | grep -E" file_in | file_out "| tail -5" Ich habe diesen verwendet.
anotherperson1
3
Ich mache mitxargs -n 1 sh -c 'echo $0'
Ginhing
1
unter macOS funktionierte der echo $0
ersatz
1
Um es mit Dateinamen mit Leerzeichen, verwenden zu arbeiten -print0, xargs -0und die Flucht {}in doppelte Anführungszeichen innerhalb des shBefehls:find . -type d -name "*log*" -print0 | xargs -0 -I {} sh -c "echo \"{}\";ls -la \"{}\" | tail -2"
Benedikt Köppel
Ich benutze "xargs -n 1 sh -c" echo \ $ 0 | $ func "` wenn ich die Variable $ func benutzen muss
god
5

GNU Parallel macht diese Art von Aufgaben einfach:

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

Wenn Sie GNU Parallel nicht vollständig installieren möchten, können Sie eine Minimalinstallation durchführen: http://git.savannah.gnu.org/cgit/parallel.git/tree/README

Ole Tange
quelle
2

Nur zusätzlich zu fredtantini und zur allgemeinen Verdeutlichung (da die Dokumente etwas verwirrend sind):

Das xargs -I {}nimmt die '{}' Zeichen von der Standardeingabe und ersetzt sie durch alles, was von der Pipe hereinkommt. Dies bedeutet, dass Sie tatsächlich durch eine {}beliebige Zeichenkombination ersetzen können (möglicherweise, um Ihrem bevorzugten Programmierstil besser zu entsprechen). Zum Beispiel : xargs -I % sh -c "echo %". Wenn Sie immer die verwenden xargs -I {}, können Sie xargs -isie durch die Kurzschrift ersetzen .

Das sh -cwird zeigen , Ihre bash / Shell den nächsten Befehl aus einer Zeichenfolge zu lesen und nicht von der Standardeingabe. Schreiben sh -c "echo something"ist also gleichbedeutend mit echo something.

Das xargs -I {} sh -c "echo {}"liest die Eingabe, mit sh -cder Sie erstellt haben echo {}. Da Sie es angewiesen haben, es durch {}die Argumente zu ersetzen, die Sie aus der Pipe erhalten haben, wird das passieren.

Sie können dies auch ohne Verrohrung problemlos testen. Geben Sie einfach den obigen Befehl in ein Terminal ein. Was auch immer Sie als Nächstes schreiben, wird an das Terminal ausgegeben (Strg-D zum Beenden).

Im ls -la {}Befehl passiert dasselbe noch einmal. Das {}wird durch den Inhalt des Pre-Pipe-Befehls ersetzt.

Borisu
quelle