2013-09-11 10 views
11

Im aktuellen Verzeichnis möchte ich den Dateinamen und den Inhalt darin drucken. Ich kann separat Dateinamen oder Inhalt vonxargs mit mehreren Befehlen

find . | grep "file_for_print" | xargs echo 
find . | grep "file_for_print" | xargs cat 

drucken, aber was ich will druckt sie zusammen wie folgt aus:

file1 
line1 inside file1 
line2 inside file1 
file2 
line1 inside file2 
line2 inside file2 

las ich xargs with multiple commands as argument und versuchte

find . | grep "file_for_print" | xargs -I % sh -c 'echo; cat;' 

aber doesn‘ t arbeiten. Ich bin nicht vertraut mit Xargs, also weiß nicht, was genau "-I% sh -c" bedeutet. könnte mir jemand helfen? Danke!

+0

dies versuchen ..... ich denke, das helfen soll, „finden |. grep‚file_for_print‘| xargs mehr“ – nsd

Antwort

14

mit zu starten, gibt es praktisch keinen Unterschied zwischen:

find . | grep "file_for_print" | xargs echo 

und

find . -name "file_for_print*" 

der Ausnahme, dass die zweiten Dateinamen nicht überein, wie this_is_not_the_file_for_print wird, und es wird den Dateinamen einen pro drucken Linie. Es wird auch viel schneller, weil es nicht die gesamte rekursive Verzeichnisstruktur erzeugen und drucken muss, nur damit grep das meiste davon wegwerfen kann.

find . -name "file_for_print*" 

ist eigentlich genau die gleiche wie

find . -name "file_for_print*" -print 

wo die -print Aktion druckt jeder angepaßter Dateiname gefolgt von einem Zeilenvorschub. Wenn Sie keine Aktionen mit find ausführen, wird davon ausgegangen, dass Sie -print möchten. Aber es hat mehr Tricks im Ärmel als das. Zum Beispiel:

find . -name "file_for_print*" -exec cat {} \; 

Die -exec Aktion Ursachen finden Sie den folgenden Befehl ausführen, bis zum \;, {} mit jedem passenden Dateinamen zu ersetzen.

find beschränkt sich nicht auf eine einzige Aktion. Du kannst es so tun, wie du willst. Also:

find . -name "file_for_print*" -print -exec cat {} \; 

wird wahrscheinlich ziemlich gut, was Sie wollen.

Für viele weitere Informationen zu diesem sehr nützlichen Programm, Typ:

man find 

oder

info find 

und alles darüber lesen.

+5

+1 für möglicherweise die sanft rtfm geliefert ;-) – necromancer

+0

ja finden und xargs sind ziemlich erstaunlich. – sashang

16

find . | grep "file_for_print" | xargs -I % sh -c 'echo %; cat %;' (OP fehlte % s)

+1

Genau das, was ich gesucht habe! Vielen Dank! – John

+0

froh, dass ich geholfen habe :-) – necromancer

0

Was ist mit Ihrer eigenen bash Funktion zu schreiben?

#!/bin/bash 

myFunction() { 
    while read -r file; do 
     echo "$file" 
     cat "$file" 
    done 
} 

find . -name "file_for_print*" | myFunction 
6

Da es noch nicht gesagt worden: -I % sagt xargs mit den Argumenten ‚%‘ zu ersetzen, in dem Befehl, den Sie geben. Die sh -c '...' bedeutet nur die Befehle '...' in einer neuen Shell ausführen.

So

xargs -I % sh -c 'echo %; cat %;' 

läuft echo [filename] für jeden Dateinamen xargs gegeben durch cat [filename] gefolgt. Die Befehle echo und cat werden in einem anderen Shell-Prozess ausgeführt, aber das spielt normalerweise keine Rolle. Ihre Version hat nicht funktioniert, weil die % Zeichen in dem an xargs übergebenen Befehl fehlten.


Für was es wert ich diesen Befehl verwenden würde, das Gleiche zu erreichen:

find -name "*file_for_print*" | parallel 'echo {}; cat {};' 

weil es einfacher (parallel automatisch {} als Ersatzzeichen verwendet und mehrere Befehle standardmäßig dauern kann).

0

In diesem speziellen Fall wird jeder Befehl sowieso für jede einzelne Datei ausgeführt, so dass die Verwendung von Xargs keinen Vorteil bringt. Sie können nur anhängen -exec zweimal zu Ihrer ‚finden‘:

find . -name "*file_for_print*" -exec echo {} \; -exec cat {} \; 

In diesem Fall -print anstelle des ersten echo verwendet werden könnten, wie durch rici darauf hingewiesen, aber dieses Beispiel zeigt die Fähigkeit, zwei beliebige Befehle auszuführen mit ein einziger find