Es gibt eine Option, mit der grep -f MY_FILE
nach Mustern gesucht werden kann, die aus einer Datei stammen, anstatt sie direkt in der Befehlszeile anzugeben.
Gibt es eine Option, mit dem find
Befehl etwas Ähnliches zu tun und ihn die zu suchenden Muster aus einer Eingabedatei lesen zu lassen?
Antwort1
find
scheint solche Fähigkeiten nicht eingebaut zu haben, aber Sie können damit mehrere Befehle mit Argumenten aus einer Datei xargs
konstruieren , wie etwa:find
xargs -a patterns.txt -I% find Pictures/ -name %
wobei hier patterns.txt
eine Liste mit Mustern steht, die für den -name
Filter 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
find
und 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
*.jpg
und ), 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:
xargs
liest eine Liste von Argumenten und verwendet diese zum Erstellen und Ausführen einer neuen Befehlszeile.-a patterns.txt
weist 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, daxargs
dafür gesorgt wird, dass jedes eingefügte Argument als einzelnes Token behandelt und nicht einzeln aufgeteilt wird. Sie können das natürlichPictures/
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-regex
das 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,$2
ist also nicht erforderlich. - Die Funktion
read_file
liest die Eingabedatei, die der erste Positionsparameter für das Skript ist. Dadurch wird ein Muster für-regex
die Flagge erstellt. - Dieses Muster wird an den „Haupt“-Block des Skripts zurückgesendet, in einer Variable gespeichert und an den Befehl
fp
übergeben .find