TL;DR: Wenn es Ihnen nur um die korrekteste Antwort geht, wollen Sie wahrscheinlich meine persönliche Präferenz (siehe unten in diesem Beitrag):
# execute `process` once for each file
find . -name '*.txt' -exec process {} \;
Wenn Sie Zeit haben, lesen Sie sich den Rest durch, um verschiedene Möglichkeiten und die Probleme mit den meisten von ihnen zu sehen.
Die vollständige Antwort:
Welcher Weg der beste ist, hängt davon ab, was Sie tun wollen, aber hier sind ein paar Möglichkeiten. Solange keine Datei oder kein Ordner im Teilbaum ein Leerzeichen im Namen hat, können Sie einfach eine Schleife über die Dateien ziehen:
for i in $x; do # Not recommended, will break on whitespace
process "$i"
done
Geringfügig besser, ohne die temporäre Variable x
:
for i in $(find -name \*.txt); do # Not recommended, will break on whitespace
process "$i"
done
Es viel Es ist besser, wenn man so oft wie möglich globiert. Leerzeichenfrei, für Dateien im aktuellen Verzeichnis:
for i in *.txt; do # Whitespace-safe but not recursive.
process "$i"
done
Durch die Aktivierung des globstar
können Sie alle passenden Dateien in diesem Verzeichnis und allen Unterverzeichnissen globieren:
# Make sure globstar is enabled
shopt -s globstar
for i in **/*.txt; do # Whitespace-safe and recursive
process "$i"
done
In einigen Fällen, z. B. wenn die Dateinamen bereits in einer Datei stehen, müssen Sie möglicherweise read
:
# IFS= makes sure it doesn't trim leading and trailing whitespace
# -r prevents interpretation of \ escapes.
while IFS= read -r line; do # Whitespace-safe EXCEPT newlines
process "$line"
done < filename
read
kann sicher verwendet werden in Kombination mit find
indem Sie das Begrenzungszeichen entsprechend setzen:
find . -name '*.txt' -print0 |
while IFS= read -r -d '' line; do
process "$line"
done
Für komplexere Suchvorgänge werden Sie wahrscheinlich die find
entweder mit seinem -exec
oder mit der Option -print0 | xargs -0
:
# execute `process` once for each file
find . -name \*.txt -exec process {} \;
# execute `process` once with all the files as arguments*:
find . -name \*.txt -exec process {} +
# using xargs*
find . -name \*.txt -print0 | xargs -0 process
# using xargs with arguments after each filename (implies one run per filename)
find . -name \*.txt -print0 | xargs -0 -I{} process {} argument
find
Sie können auch in das Verzeichnis der einzelnen Dateien wechseln, bevor Sie einen Befehl ausführen, indem Sie -execdir
代わりに -exec
und kann interaktiv gemacht werden (Eingabeaufforderung vor Ausführung des Befehls für jede Datei) mit -ok
代わりに -exec
(ou -okdir
代わりに -execdir
).
*: Technisch gesehen, sind beide find
y xargs
(standardmäßig) führt den Befehl mit so vielen Argumenten aus, wie in die Befehlszeile passen, und zwar so oft, wie es nötig ist, um alle Dateien zu durchsuchen. In der Praxis spielt das keine Rolle, es sei denn, Sie haben eine sehr große Anzahl von Dateien, und wenn Sie die Länge überschreiten, aber alle in der gleichen Befehlszeile benötigen, Sie sind SOL einen anderen Weg finden.