TL; DR: Si vous êtes juste ici pour la réponse la plus correcte, vous voulez probablement ma préférence personnelle find . -name '*.txt' -exec process {} \;
(voir le bas de cet article). Si vous avez le temps, lisez le reste pour voir plusieurs façons différentes et les problèmes avec la plupart d'entre elles.
La réponse complète:
La meilleure façon dépend de ce que vous voulez faire, mais voici quelques options. Tant qu'aucun fichier ou dossier dans la sous-arborescence n'a d'espace dans son nom, vous pouvez simplement parcourir les fichiers:
for i in $x; do # Not recommended, will break on whitespace
process "$i"
done
Un peu mieux, supprimez la variable temporaire x
:
for i in $(find -name \*.txt); do # Not recommended, will break on whitespace
process "$i"
done
Il est beaucoup mieux glob quand vous le pouvez. Sécuritaire pour les espaces blancs, pour les fichiers du répertoire courant:
for i in *.txt; do # Whitespace-safe but not recursive.
process "$i"
done
En activant l' globstar
option, vous pouvez glober tous les fichiers correspondants dans ce répertoire et tous les sous-répertoires:
# Make sure globstar is enabled
shopt -s globstar
for i in **/*.txt; do # Whitespace-safe and recursive
process "$i"
done
Dans certains cas, par exemple si les noms de fichiers sont déjà dans un fichier, vous devrez peut-être utiliser 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
peut être utilisé en toute sécurité en combinaison avec find
en définissant le délimiteur de manière appropriée:
find . -name '*.txt' -print0 |
while IFS= read -r -d '' line; do
process "$line"
done
Pour des recherches plus complexes, vous voudrez probablement utiliser find
, soit avec son -exec
option, soit avec -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
peut également se placer dans le répertoire de chaque fichier avant d'exécuter une commande en utilisant -execdir
au lieu de -exec
, et peut être rendu interactif (demander avant d'exécuter la commande pour chaque fichier) en utilisant -ok
au lieu de -exec
(ou -okdir
au lieu de -execdir
).
*: Techniquement, les deux find
et xargs
(par défaut) exécuteront la commande avec autant d'arguments qu'ils peuvent tenir sur la ligne de commande, autant de fois qu'il faut pour parcourir tous les fichiers. En pratique, à moins que vous n'ayez un très grand nombre de fichiers, cela n'aura pas d'importance, et si vous dépassez la longueur mais que vous en avez tous besoin sur la même ligne de commande, vous êtes SOL trouver une manière différente.