Gibt es eine Möglichkeit find
, eine in der Shell definierte Funktion auszuführen? Beispielsweise:
dosomething () {
echo "doing something with $1"
}
find . -exec dosomething {} \;
Das Ergebnis davon ist:
find: dosomething: No such file or directory
Gibt es eine Möglichkeit zu bekommen find
s‘ -exec
zu sehen dosomething
?
$0
.find . -exec bash -c 'dosomething "$0"' {} \;
, werden Leerzeichen (und andere seltsame Zeichen) in Dateinamen behandelt ...export -f
funktioniert nur in einigen Versionen von Bash. Es ist nicht posix, nicht crossplatforn,/bin/sh
wird einen Fehler damit habenquelle
while read
für eine for-Schleife gewechselt habe .for item in $(find . ); do some_function "${item}"; done
Jaks Antwort oben ist großartig, hat aber ein paar Fallstricke, die leicht zu überwinden sind:
Dies verwendet null als Trennzeichen anstelle eines Zeilenvorschubs, sodass Dateinamen mit Zeilenvorschub funktionieren. Es wird auch das
-r
Flag verwendet, das das Escaping von Backslashs deaktiviert, ohne dass Backslashes in Dateinamen nicht funktionieren. Es wird auch gelöscht,IFS
damit potenzielle nachgestellte Leerzeichen in Namen nicht verworfen werden.quelle
/bin/bash
, wird aber nicht funktionieren/bin/sh
. Wie schade.Fügen Sie Anführungszeichen
{}
wie unten gezeigt hinzu:Dies korrigiert alle Fehler aufgrund von Sonderzeichen, die von zurückgegeben werden
find
, z. B. Dateien mit Klammern im Namen.quelle
{}
. Dies wird für einen Dateinamen mit doppelten Anführungszeichen unterbrochen.touch '"; rm -rf .; echo "I deleted all you files, haha
. Hoppla.-exec bash -c 'echo $0' '{}' \;
Beachten Sie, dass bei Verwendungbash -c
$ 0 das erste Argument ist, nicht der Skriptname.Verarbeitung führt zu Bulk
Um die Effizienz zu steigern, verarbeiten viele Menschen
xargs
Ergebnisse in großen Mengen, dies ist jedoch sehr gefährlich. Aus diesem Grund wurde eine alternative Methode eingeführtfind
, mit der Ergebnisse in großen Mengen ausgeführt werden.Beachten Sie jedoch, dass diese Methode möglicherweise mit einigen Einschränkungen verbunden ist, z. B. einer Anforderung in POSIX
find
, die{}
am Ende des Befehls gelten muss.find
Übergibt viele Ergebnisse als Argumente an einen einzelnen Aufruf vonbash
und diefor
Schleife durchläuft diese Argumente und führt die Funktiondosomething
für jedes dieser Argumente aus.Die obige Lösung beginnt mit Argumenten
$1
, weshalb es ein_
(was darstellt$0
) gibt.Verarbeitungsergebnisse nacheinander
Ebenso denke ich, dass die akzeptierte Top-Antwort korrigiert werden sollte, um zu sein
Dies ist nicht nur vernünftiger, da Argumente immer bei beginnen sollten
$1
, sondern auch die Verwendung von$0
kann zu unerwartetem Verhalten führen, wenn der von zurückgegebene Dateinamefind
eine besondere Bedeutung für die Shell hat.quelle
Lassen Sie das Skript sich selbst aufrufen und übergeben Sie jedes gefundene Element als Argument:
Wenn Sie das Skript selbst ausführen, findet es, wonach Sie suchen, und ruft sich selbst auf, wobei jedes Suchergebnis als Argument übergeben wird. Wenn das Skript mit einem Argument ausgeführt wird, führt es die Befehle für das Argument aus und wird dann beendet.
quelle
find: ‘myscript.sh’: No such file or directory
bash myscript.sh
Für diejenigen unter Ihnen, die nach einer Bash-Funktion suchen, die einen bestimmten Befehl für alle Dateien im aktuellen Verzeichnis ausführt, habe ich einen der folgenden Antworten zusammengestellt:
Beachten Sie, dass es mit Dateinamen bricht, die Leerzeichen enthalten (siehe unten).
Nehmen Sie als Beispiel diese Funktion:
Angenommen, ich wollte alle Instanzen von Hallo in allen Dateien im aktuellen Verzeichnis in Welt ändern. Ich würde tun:
Verwenden Sie zur Sicherheit mit Symbolen in Dateinamen:
(aber du brauchst ein
find
, das-print0
zB GNU handhabtfind
).quelle
Ich finde den einfachsten Weg wie folgt: Ich wiederhole zwei Befehle in einem einzigen Schritt
quelle
Als Referenz vermeide ich dieses Szenario mit:
Holen Sie sich die Ausgabe von find in der aktuellen Skriptdatei und durchlaufen Sie die Ausgabe nach Bedarf. Ich stimme der akzeptierten Antwort zu, möchte aber keine Funktion außerhalb meiner Skriptdatei verfügbar machen.
quelle
Es ist nicht möglich, eine Funktion auf diese Weise auszuführen.
Um dies zu überwinden, können Sie Ihre Funktion in ein Shell-Skript einfügen und diese von aufrufen
find
Verwenden Sie es jetzt in find als:
quelle
dosomething $1
=>dosomething "$1"
und starten Sie Ihre Datei korrekt mitfind . -exec bash dosomething.sh {} \;
Legen Sie die Funktion in eine separate Datei und
find
führen Sie diese aus.Shell-Funktionen befinden sich innerhalb der Shell, in der sie definiert sind.
find
wird sie niemals sehen können.quelle
Wenn Sie die Bulk-Option für
exec
oderexecdir
(-exec command {} +
) verwenden und alle Positionsargumente abrufen möchten, um Ergänzungen und Erläuterungen zu einigen anderen Antworten bereitzustellen , müssen Sie die Behandlung$0
mit berücksichtigenbash -c
. Betrachten Sie genauer den folgenden Befehl, derbash -c
wie oben vorgeschlagen verwendet wird, und geben Sie einfach Dateipfade aus, die mit '.wav' enden, aus jedem gefundenen Verzeichnis:Das Bash-Handbuch sagt:
Hier
'check $@'
ist die Befehlszeichenfolge und_ {}
sind die Argumente nach der Befehlszeichenfolge. Beachten Sie, dass dies$@
ein spezieller Positionsparameter in bash ist, der ab 1 auf alle Positionsparameter erweitert wird . Beachten Sie auch, dass bei dieser-c
Option das erste Argument dem Positionsparameter zugewiesen wird$0
. Das heißt, wenn Sie versuchen, auf alle Positionsparameter mit zuzugreifen$@
, erhalten Sie nur Parameter ab$1
und nach. Dies ist der Grund, warum Dominiks Antwort das_
Dummy-Argument zum Füllen von Parametern enthält$0
, sodass alle gewünschten Argumente später verfügbar sind, wenn wir beispielsweise die$@
Parametererweiterung oder die for-Schleife wie in dieser Antwort verwenden.Ähnlich wie bei der akzeptierten Antwort
bash -c 'shell_function $0 $@'
würde dies natürlich auch durch explizites Übergeben funktionieren$0
, aber auch hier müssten Sie bedenken, dass dies$@
nicht wie erwartet funktioniert.quelle
Nicht direkt, nein. Die Suche wird in einem separaten Prozess ausgeführt, nicht in Ihrer Shell.
Erstellen Sie ein Shell-Skript, das den gleichen Job wie Ihre Funktion ausführt, und finden Sie
-exec
das.quelle
Ich würde es ganz vermeiden
-exec
. Warum nicht verwendenxargs
?quelle