So durchsuchen Sie Tausende von Dateien in einem Verzeichnis nach Hunderten von Zeichenfolgen in einer Datei


11

Ich versuche eine grepErklärung zu verfassen und sie bringt mich um. Ich bin es auch leid, den arguments list too longFehler zu bekommen. Ich habe eine Datei, nennen wir sie subset.txt. Es enthält Hunderte von Zeilen mit bestimmten Zeichenfolgen wie z MO43312948. In meinem Objektverzeichnis befinden sich Tausende von Dateien, und ich muss alle Dateien, die die darin aufgeführten Zeichenfolgen enthalten, subset.txtin ein anderes Verzeichnis kopieren .

Ich habe versucht, damit zu beginnen, um nur die passenden Dateien aus dem Objektverzeichnis zurückzugeben.

grep -F "$(subset.txt)" /objects/*

Ich bekomme immer `bash: / bin / grep: Argumentliste zu lang``


6
Warum haben Sie "$(subset.txt)"den Befehl so eingegeben? Dies ist eine Befehlsersetzung , durch die Ihre Shell ausgeführt wird subset.txt (als wäre es ein Befehl oder ein Skript).
JigglyNaga

Antworten:


23

Sie können ein Verzeichnis als Ziel an grepwith -Rund eine Datei mit Eingabemustern übergeben mit -f:

  -f FILE, --file=FILE
          Obtain patterns from FILE, one per line.  If this option is used
          multiple  times  or  is  combined with the -e (--regexp) option,
          search for all patterns given.  The  empty  file  contains  zero
          patterns, and therefore matches nothing.

   -R, --dereference-recursive
          Read all files under each directory,  recursively.   Follow  all
          symbolic links, unlike -r.

Sie suchen also:

grep -Ff subset.txt -r objects/

Sie können die Liste der übereinstimmenden Dateien abrufen mit:

grep -Flf subset.txt -r objects/

Wenn Ihre endgültige Liste nicht zu lang ist, können Sie einfach Folgendes tun:

 mv $(grep -Flf subset.txt -r objects/) new_dir/

Wenn dies einen argument list too longFehler zurückgibt , verwenden Sie:

grep -Flf subset.txt -r objects/ | xargs -I{} mv {} bar/

Und wenn Ihre Dateinamen Leerzeichen oder andere seltsame Zeichen enthalten können, verwenden Sie (unter der Annahme von GNU grep):

grep -FZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

Wenn Sie Binärdateien ausschließen möchten, verwenden Sie:

grep -IFZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

… Oder um potenziell Tausende von mvAufrufen mit jeweils einem Argument zu vermeiden : ... | xargs -0 mv -t bar/(vorausgesetzt, Sie mvunterstützen die -tOption).
David Foerster

11

verwenden

grep -F -f subset.txt 

um grep anzuweisen, aus der subset.txtDatei zu lesen .

Sie können find verwenden, um die Datei zu durchsuchen.

find . -type f -exec grep -F -f subset.txt {} \;

oder

find . -type f -exec grep -F -f subset.txt {}  +

Gibt es einen Vorteil der Verwendung findanstelle einer -randeren Filterung?
Phk

1
@phk grep -rsucht in Symlinks zu regulären Dateien, was möglicherweise wünschenswert ist oder nicht (wenn sie auf denselben Baum zeigen, durchsuchen Sie dieselbe Datei zweimal; wenn sie nach außen zeigen, suchen Sie eine Datei, die möglicherweise nicht vorhanden ist erwünscht sein).
Gilles 'SO - hör auf böse zu sein'

Moderne Versionen von grephaben Optionen, um ihre Interaktion mit symbolischen Links zu steuern ( man grepum die Besonderheiten für das aktuelle System zu bestimmen). Ein Rekursiv grepist viel schneller als das grepindividuelle Ausführen jeder Datei über find.
Perry

1
@Perry bist du dir da sicher? Warum? Beachten Sie außerdem, dass diese Antwort verwendet wird -exec +, sodass Dateien gruppiert werden und nicht ein Grep pro Datei ausgeführt wird.
Terdon

Ich korrigierte stehen, ich war nicht bewusst, die verschiedenen Semantik -exec {} +vs -exec {} \;... Sie jeden Tag etwas Neues zu lernen (ich noch keinen Grund , warum eine einzelne rekursive grepschneller sein würde nicht als mehrere greps läuft von findwegen Prozesserstellung und Muster - Parsing - Overhead , aber ich Ich habe keine spezifischen Zahlen zur Hand, um das zu belegen.
Perry

3

Wenn Sie grep noch weiter beschleunigen möchten, können Sie das Gebietsschema in Ihrer Shell festlegen, bevor Sie es ausführen, dh "LC_ALL = c" verwenden. Dies wird an grep vererbt und deaktiviert die Unicode-Verarbeitung, wenn dies nicht erforderlich ist. In einigen Fällen kann dies grep erheblich beschleunigen. Ein großartiger Blog, der dies dokumentiert, finden Sie unter http://www.inmotionhosting.com/support/website/ssh/speed-up-grep-searches-with-lc-all . Dieser Trick kann auch Bash-Shell-Skripte beschleunigen, nicht nur grep.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.