Mit dem Befehl „Find“ nach mehreren Mustern in einer Datei suchen

Mit dem Befehl „Find“ nach mehreren Mustern in einer Datei suchen

Es gibt eine Option, mit der grep -f MY_FILEnach Mustern gesucht werden kann, die aus einer Datei stammen, anstatt sie direkt in der Befehlszeile anzugeben.

Gibt es eine Option, mit dem findBefehl etwas Ähnliches zu tun und ihn die zu suchenden Muster aus einer Eingabedatei lesen zu lassen?

Antwort1

findscheint solche Fähigkeiten nicht eingebaut zu haben, aber Sie können damit mehrere Befehle mit Argumenten aus einer Datei xargskonstruieren , wie etwa:find

xargs -a patterns.txt -I% find Pictures/ -name %

wobei hier patterns.txteine Liste mit Mustern steht, die für den -nameFilter geeignet sind, ein Muster pro Zeile. Achten Sie darauf, dass Sie keine führenden/nachgestellten Leerzeichen darin haben, da diese in das Muster aufgenommen werden. Ein Beispiel:

*.jpg
2018-06-*
*foo*
unicorn.png

Notiz:Obwohl diese Antwort recht einfach und elegant aussieht, wurde in den Kommentaren richtigerweise darauf hingewiesen, dass sie auch einige Nachteile hat:

Bei großen Ordnern oder vielen Mustern ist die Leistung nicht besonders gut, da das Programm einmal pro Muster in Ihrer Datei ausgeführt wird findund dadurch der gesamte Suchordner wiederholt gescannt wird.

Aus diesem Grund werden Dateien, die mehr als einem Muster entsprechen, auch dann, wenn Sie mehrere Muster haben, die sich möglicherweise überschneiden (wie *.jpgund ), im Ergebnis entsprechend oft angezeigt. Wenn Sie ohnehin nur die Namen drucken, können Sie die Ausgabe weiterleiten , um Duplikate zu entfernen. Wenn Sie jedoch beispielsweise diese Ergebnisse entfernen oder Befehle darauf ausführen, ist dies möglicherweise weniger wünschenswert.*foo*sort -u-exec

Wenn einer dieser Nachteile für Ihren Anwendungsfall ein Problem darstellt, sollten Sie sich vielleicht besser für eine der alternativen Antworten entscheiden.

Erklärung des Befehls:

  • xargsliest eine Liste von Argumenten und verwendet diese zum Erstellen und Ausführen einer neuen Befehlszeile.
  • -a patterns.txtweist es an, aus dieser Datei statt von der Standardeingabe zu lesen.
  • -I%weist ihn an, die gelesenen Argumente nicht einfach an das Ende der Befehlszeile anzuhängen, sondern das %von Ihnen in der Befehlszeile angegebene Zeichen durch ein Argument zu ersetzen. Dies bedeutet, dass für jedes Eingabeargument ein separater Befehl erstellt und ausgeführt wird.
  • find Pictures/ -name %ist die Befehlszeile, in die wir die Argumente einfügen möchten, wobei wir das ersetzen %. Sie brauchen hier keine Anführungszeichen, da xargsdafür gesorgt wird, dass jedes eingefügte Argument als einzelnes Token behandelt und nicht einzeln aufgeteilt wird. Sie können das natürlich Pictures/durch Ihr eigenes Suchverzeichnis ersetzen und auch einen anderen und/oder mehr Filter als nur verwenden -name. Da wir die Einfügeoption verwenden, können Sie auch Aktionen wie -exec ...an das Ende des Befehls anhängen.

Antwort2

Sie können einfach mit einen regulären Ausdruck aus dem Inhalt Ihrer Datei erstellen paste -sd'|' bar.

find ~/foo -regextype egrep -regex "^.*/($(paste -sd'|' bar))$"

Der reguläre Ausdruck wird"^.*/(a|b)$"

Antwort3

Vor nicht allzu langer Zeit habe ich eineAntwort-regexdas mehrere Muster mithilfe von Flags in kombiniert find. Darauf basierend können wir ein kleines Skript oder eine Funktion erstellen, die dieselbe Aufgabe erfüllt, aber die Liste der Muster aus einer Datei erstellt.

#!/bin/bash

read_file(){
    local full_pattern=""
    while IFS= read -r pattern; do
        if [ -z "$full_pattern"  ];then
            full_pattern="$pattern"
            continue
        fi
        full_pattern="$full_pattern\|$pattern"
    done < "$1"
    echo "$full_pattern"
}

fp=$(read_file "$1" )
find "$2" -type f -regex ".*\($fp\).*$" 

Was dies bewirkt:

  • Wir rufen das Skript wie folgt auf findf.sh input.txt /etc: Der erste Positionsparameter ist die Datei mit den Mustern und der zweite das Verzeichnis, in dem gesucht werden soll. GNU find geht von .einem Verzeichnis aus, wenn das Verzeichnisargument weggelassen wird, $2ist also nicht erforderlich.
  • Die Funktion read_fileliest die Eingabedatei, die der erste Positionsparameter für das Skript ist. Dadurch wird ein Muster für -regexdie Flagge erstellt.
  • Dieses Muster wird an den „Haupt“-Block des Skripts zurückgesendet, in einer Variable gespeichert und an den Befehl fpübergeben .find

verwandte Informationen