Ich mache eine find
und bekomme dann eine Liste von Dateien. Wie leite ich es an ein anderes Dienstprogramm wie cat
(damit cat den Inhalt all dieser Dateien anzeigt) und brauche im Grunde grep
etwas aus diesen Dateien.
Ich mache eine find
und bekomme dann eine Liste von Dateien. Wie leite ich es an ein anderes Dienstprogramm wie cat
(damit cat den Inhalt all dieser Dateien anzeigt) und brauche im Grunde grep
etwas aus diesen Dateien.
Antworten:
Weiterleitung an einen anderen Prozess (obwohl dies NICHT das erreicht, was Sie gesagt haben, dass Sie versuchen zu tun):
command1 | command2
Dadurch wird die Ausgabe von Befehl1 als Eingabe von Befehl2 gesendet
-exec
auf a find
(dies wird tun, was Sie tun möchten - ist aber spezifisch für find
)
find . -name '*.foo' -exec cat {} \;
(Alles zwischen find
und -exec
sind die Suchprädikate, die Sie bereits verwendet haben. {}
Ersetzt die bestimmte Datei, die Sie im Befehl gefunden haben ( cat {}
in diesem Fall). Dies \;
ist das Beenden des -exec
Befehls.)
Senden Sie die Ausgabe eines Prozesses als Befehlszeilenargumente an einen anderen Prozess
command2 `command1`
beispielsweise:
cat `find . -name '*.foo' -print`
(Beachten Sie, dass dies BACK-QUOTES sind, keine regulären Anführungszeichen (unter der Tilde ~ auf meiner Tastatur).) Dadurch wird die Ausgabe von command1
in command2
als Befehlszeilenargumente gesendet. Beachten Sie jedoch, dass Dateinamen mit Leerzeichen (Zeilenumbrüche usw.) in separate Argumente unterteilt werden.
find
Folgendes schreiben können : find . -name '*.foo' -exec cat {} +
, wobei +
angegeben wird, dass find
so viele Dateinamen wie möglich in einem einzigen Befehlsaufruf zusammengefasst werden sollen. Dies ist sehr nützlich (es behandelt Leerzeichen usw. in Dateinamen, ohne auf -print0
und zurückzugreifen xargs -0
).
find . -name '*.foo' | xargs cat
find . -name '*.foo' | xargs cat | grep string
POSIX 2008 hat den +
Marker hinzugefügt , find
was bedeutet, dass jetzt automatisch so viele Dateien wie möglich in einer einzigen Befehlsausführung zusammengefasst werden, ähnlich wie dies der xargs
Fall ist, jedoch mit einer Reihe von Vorteilen:
Das Problem mit xargs
dem Dateinamen ist ein Problem ohne die -0
Option, und das Problem "Auch ohne Dateinamen ausführen" ist ein Problem mit oder ohne die -0
Option - aber GNU xargs
hat die Option -r
oder --no-run-if-empty
, um dies zu verhindern. Außerdem reduziert diese Notation die Anzahl der Prozesse, nicht dass Sie wahrscheinlich den Leistungsunterschied messen. Daher könnte man vernünftigerweise schreiben:
find . -exec grep something {} +
find . -print | xargs grep something
Wenn Sie unter Linux arbeiten oder über GNU find
und xargs
Befehle verfügen , verwenden Sie -print0
mit find
und -0
mit xargs
Dateinamen, die Leerzeichen und andere ungerade Zeichen enthalten.
find . -print0 | xargs -0 grep something
grep
Wenn Sie die Dateinamen (nur den Text) nicht möchten, fügen Sie eine entsprechende Option hinzu grep
(normalerweise -h
zum Unterdrücken von 'Überschriften'). Um absolut zu gewährleisten, dass der Dateiname von gedruckt wird grep
(auch wenn nur eine Datei gefunden wird oder der letzte Aufruf von grep
nur 1 Dateinamen enthält), fügen Sie ihn /dev/null
zur xargs
Befehlszeile hinzu, sodass immer mindestens zwei Dateinamen vorhanden sind.
xargs grep something
.
find
wird an den Standardeingang von weitergeleitet xargs
. Das xargs
Programm liest seine Standardeingabe, teilt die Eingabe im Leerraum (Leerzeichen, Zeilenumbrüche, Tabulatoren usw.) auf, hängt eine Reihe von Wörtern an den Befehl an grep something
und führt die Befehlszeile aus. xargs
Lesen Sie dann die Eingabe weiter und führen Sie die Befehle aus, bis die Eingabe aufgebraucht ist. xargs
führt den grep
Befehl so oft aus, wie es für die Eingabe erforderlich ist ( find
in diesem Beispiel).
/dev/null
die Fehlermeldungen zu verlieren.
Es gibt einige Möglichkeiten, die Liste der vom find
Befehl zurückgegebenen Dateien an den Befehl zu übergeben cat
, obwohl technisch nicht alle Piping verwenden und keine direkt an cat
.
Am einfachsten ist es, backticks ( `
) zu verwenden:
cat `find [whatever]`
Dies nimmt die Ausgabe von find
und platziert sie effektiv in der Befehlszeile von cat
. Dies funktioniert nicht gut, wenn find
zu viel ausgegeben wird (mehr als in eine Befehlszeile passen kann) oder wenn die Ausgabe Sonderzeichen enthält (wie Leerzeichen).
In einigen Shells, einschließlich bash
, kann man $()
anstelle von Backticks verwenden:
cat $(find [whatever])
Dies ist weniger portabel, aber verschachtelbar. Abgesehen davon hat es so ziemlich die gleichen Einschränkungen wie Backticks.
Da das Ausführen anderer Befehle für das, was gefunden wurde, häufig verwendet find
wird, verfügt find über eine -exec
Aktion, die einen Befehl für jede gefundene Datei ausführt:
find [whatever] -exec cat {} \;
Das {}
ist ein Platzhalter für den Dateinamen und \;
markiert das Ende des Befehls (es ist möglich, dass danach andere Aktionen ausgeführt werden -exec
.)
Dies wird cat
einmal für jede einzelne Datei ausgeführt, anstatt eine einzelne Instanz auszuführen, in der cat
mehrere Dateinamen übergeben werden. Dies kann ineffizient sein und möglicherweise nicht das gewünschte Verhalten für einige Befehle aufweisen (obwohl dies für in Ordnung ist cat
). Die Syntax ist auch umständlich einzugeben - Sie müssen das Semikolon umgehen, da das Semikolon für die Shell etwas Besonderes ist!
Einige Versionen von find
(vor allem der GNU - Version) können Sie ersetzen ;
mit +
zu verwenden -exec
‚s Zufügen - Modus zu weniger Instanzen ausführen cat
:
find [whatever] -exec cat {} +
Dadurch werden an jeden Aufruf von mehrere Dateinamen übergeben cat
, was effizienter sein kann.
Beachten Sie jedoch, dass nicht garantiert wird, dass ein einzelner Aufruf verwendet wird. Wenn die Befehlszeile zu lang wäre, werden die Argumente auf mehrere Aufrufe von verteilt cat
. Für cat
diese ist wahrscheinlich keine große Sache, aber für einige andere Befehle kann dies das Verhalten in unerwünschter Weise verändern. Auf Linux-Systemen ist die Beschränkung der Befehlszeilenlänge recht groß, sodass die Aufteilung in mehrere Aufrufe im Vergleich zu einigen anderen Betriebssystemen eher selten ist.
Der klassische / tragbare Ansatz besteht darin, Folgendes zu verwenden xargs
:
find [whatever] | xargs cat
xargs
führt den angegebenen Befehl aus ( cat
in diesem Fall) und fügt Argumente hinzu, die auf dem basieren, was von stdin gelesen wird. Genau wie -exec
bei +
wird dadurch die Befehlszeile bei Bedarf unterbrochen. Das heißt, wenn find
zu viel Ausgabe erzeugt wird, wird sie cat
mehrmals ausgeführt. Wie bereits in diesem Abschnitt -exec
erwähnt, gibt es einige Befehle, bei denen diese Aufteilung zu einem anderen Verhalten führen kann. Beachten Sie, dass die Verwendung auf xargs
diese Weise Probleme mit Leerzeichen in Dateinamen hat, da xargs
nur Leerzeichen als Trennzeichen verwendet werden.
Die robusteste, tragbarste und effizienteste Methode verwendet außerdem xargs
:
find [whatever] -print0 | xargs -0 cat
Das -print0
Flag weist find
an, \0
Trennzeichen (Nullzeichen) zwischen Dateinamen zu verwenden, und das -0
Flag weist xargs
an, diese \0
Trennzeichen zu erwarten . Dies hat ein ziemlich identisches Verhalten wie der -exec
... +
Ansatz, ist jedoch portabler (aber leider ausführlicher).
ls
.
$()
auch mit anderen Befehlen als find
.
Klingt für mich nach einem Job für ein Shell-Skript:
for file in 'find -name *.xml'
do
grep 'hello' file
done
oder etwas ähnliches
Der Befehl find hat ein Argument -exec, das Sie für solche Dinge verwenden können. Sie können das grep einfach direkt damit ausführen.
Zum Beispiel ( von hier aus andere gute Beispiele auf dieser Seite ):
find . -exec grep "www.athabasca" '{}' \; -print
In Bash wäre Folgendes angemessen:
find /dir -type f -print0 | xargs -0i cat {} | grep whatever
Dadurch werden alle Dateien im /dir
Verzeichnis gefunden und die Dateinamen xargs
sicher weitergeleitet, wodurch sie sicher fahren grep
.
Das Überspringen xargs
ist keine gute Idee, wenn Sie viele tausend Dateien haben /dir
. cat
wird aufgrund übermäßiger Länge der Argumentliste unterbrochen. xargs
wird das alles für Sie klären.
Das -print0
zu find
vernetzende Argument mit dem -0
Argument, xargs
Dateinamen mit Leerzeichen richtig zu behandeln. Mit dem -i
Argument to xargs
können Sie den Dateinamen an der erforderlichen Stelle in die cat
Befehlszeile einfügen . Die Klammern werden durch den Dateinamen ersetzt, der in den cat
Befehl von weitergeleitet wird find
.
Das funktioniert bei mir
find _CACHE_* | while read line; do
cat "$line" | grep "something"
done
Verwenden Sie ggrep .
ggrep -H -R -I "mysearchstring" *
um nach einer Datei unter Unix zu suchen, die Text enthält, der sich im aktuellen Verzeichnis oder in einem Unterverzeichnis befindet
Dadurch werden der Name und der Inhalt von Dateien nur rekursiv gedruckt.
find . -type f -printf '\n\n%p:\n' -exec cat {} \;
Bearbeiten (verbesserte Version): Hiermit werden Name und Inhalt von Textdateien (ASCII) nur rekursiv gedruckt.
find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'
Noch ein Versuch
find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;
Versuchen Sie, Text in Dateien zu finden? Sie können einfach grep dafür verwenden ...
grep searchterm *
Zum Auflisten und Anzeigen des Inhalts aller abc.def-Dateien auf einem Server in den Verzeichnissen / ghi und / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;
Um die abc.def-Dateien mit kommentierten Einträgen aufzulisten und anzuzeigen, sehen Sie sich diese Einträge in den Verzeichnissen / ghi und / jkl an
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
find -name '*.foo' -print
hat großartig für mich gearbeitet ... Danke