Mise à jour 2020 pour les utilisateurs Linux:
Si vous avez une version de bash (4,4-alpha ou mieux) la mise à jour, comme vous le faites probablement si vous êtes sous Linux, alors vous devriez utiliser la réponse de Benjamin W. .
Si vous êtes sur Mac OS, qui - j'ai vérifié la dernière fois - utilisait encore bash 3.2, ou si vous utilisez un autre bash, passez à la section suivante.
Réponse pour bash 4.3 ou version antérieure
Voici une solution pour obtenir la sortie de finddans un bashtableau:
array=()
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done < <(find . -name "${input}" -print0)
Ceci est délicat car, en général, les noms de fichiers peuvent avoir des espaces, de nouvelles lignes et d'autres caractères hostiles au script. La seule façon d'utiliser findet de séparer en toute sécurité les noms de fichiers les uns des autres consiste à utiliser -print0qui imprime les noms de fichiers séparés par un caractère nul. Ce ne serait pas très gênant si les fonctions readarray/ mapfilefonctions de bash supportaient les chaînes séparées par des valeurs nulles, mais ce n'est pas le cas. Bash le readfait et cela nous conduit à la boucle ci-dessus.
[Cette réponse a été rédigée à l'origine en 2014. Si vous disposez d'une version récente de bash, veuillez consulter la mise à jour ci-dessous.]
Comment ça fonctionne
La première ligne crée un tableau vide: array=()
Chaque fois que l' readinstruction est exécutée, un nom de fichier séparé par des valeurs nulles est lu à partir de l'entrée standard. L' -roption indique readde laisser les caractères antislash seuls. Le -d $'\0'indique readque l'entrée sera séparée par des valeurs nulles. Puisque nous omettons le nom read, le shell met l'entrée dans le nom par défaut: REPLY.
L' array+=("$REPLY")instruction ajoute le nouveau nom de fichier au tableau array.
La dernière ligne combine la redirection et la substitution de commande pour fournir la sortie de findà l'entrée standard de la whileboucle.
Pourquoi utiliser la substitution de processus?
Si nous n'utilisons pas de substitution de processus, la boucle pourrait être écrite comme suit:
array=()
find . -name "${input}" -print0 >tmpfile
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done <tmpfile
rm -f tmpfile
Dans ce qui précède, la sortie de findest stockée dans un fichier temporaire et ce fichier est utilisé comme entrée standard dans la boucle while. L'idée de la substitution de processus est de rendre ces fichiers temporaires inutiles. Donc, au lieu de whiledemander à la boucle de récupérer son stdin tmpfile, nous pouvons lui demander de récupérer son stdin <(find . -name ${input} -print0).
La substitution de processus est très utile. Dans de nombreux endroits où une commande souhaite lire à partir d'un fichier, vous pouvez spécifier la substitution de processus <(...), au lieu d'un nom de fichier. Il existe une forme analogue,, >(...)qui peut être utilisée à la place d'un nom de fichier où la commande veut écrire dans le fichier.
Comme les tableaux, la substitution de processus est une fonctionnalité de bash et d'autres shells avancés. Il ne fait pas partie du standard POSIX.
Alternative: lastpipe
Si vous le souhaitez, lastpipepeut être utilisé à la place de la substitution de processus (chapeau: César ):
set +m
shopt -s lastpipe
array=()
find . -name "${input}" -print0 | while IFS= read -r -d $'\0'; do array+=("$REPLY"); done; declare -p array
shopt -s lastpipedit à bash d'exécuter la dernière commande du pipeline dans le shell actuel (pas en arrière-plan). De cette façon, le arrayreste en existence une fois le pipeline terminé. Parce lastpipeque ne prend effet que si le contrôle des tâches est désactivé, nous exécutons set +m. (Dans un script, contrairement à la ligne de commande, le contrôle des travaux est désactivé par défaut.)
Notes complémentaires
La commande suivante crée une variable shell, pas un tableau shell:
array=`find . -name "${input}"`
Si vous souhaitez créer un tableau, vous devez placer des parens autour de la sortie de find. Donc, naïvement, on pourrait:
array=(`find . -name "${input}"`)
Le problème est que le shell effectue la division des mots sur les résultats de findafin que les éléments du tableau ne soient pas garantis comme vous le souhaitez.
Mise à jour 2019
À partir de la version 4.4-alpha, bash prend désormais en charge une -doption pour que la boucle ci-dessus ne soit plus nécessaire. Au lieu de cela, on peut utiliser:
mapfile -d $'\0' array < <(find . -name "${input}" -print0)
Pour plus d' informations à ce sujet , s'il vous plaît voir (et upvote) la réponse de Benjamin W. .