J'essaie de lire la sortie d'une commande dans bash en utilisant un while loop
.
while read -r line
do
echo "$line"
done <<< $(find . -type f)
La sortie que j'ai
ranveer@ranveer:~/tmp$ bash test.sh
./test.py ./test1.py ./out1 ./test.sh ./out ./out2 ./hello
ranveer@ranveer:~/tmp$
Après cela, j'ai essayé
$(find . -type f) |
while read -r line
do
echo "$line"
done
mais il a généré une erreur test.sh: line 5: ./test.py: Permission denied
.
Alors, comment puis-je le lire ligne par ligne parce que je pense qu'actuellement, il sape la ligne entière à la fois.
Sortie requise:
./test.py
./test1.py
./out1
./test.sh
./out
./out2
./hello
Il y a une erreur, vous avez besoin de < <(command)
pas <<<$(command)
< <( )
est un Substitution de processus , $()
est un substitution de commande et <<<
est une chaîne ici .
Notez que rien n'empêche les noms de fichiers de contenir des caractères de nouvelle ligne. La manière canonique d'exécuter une commande pour chaque fichier trouvé par find est.
find . -type f -exec cmd {} \;
Et si vous voulez que les choses se fassent en bash:
find . -type f -exec bash -c '
for file do
something with "$file"
done' bash {} +
De plus, la manière canonique d'appeler la commande "read" dans les scripts (si vous ne voulez pas qu'elle fasse un traitement supplémentaire sur l'entrée) est:
IFS= read -r var
-r
consiste à empêcher read
de traiter spécialement les barres obliques inverses (comme un caractère d'échappement pour les séparateurs et les sauts de ligne), et IFS = pour définir la liste des séparateurs sur la chaîne vide pour read
(sinon si n'importe quel caractère d'espacement était dans cette liste, ils seraient supprimés du début et de la fin de l'entrée).
L'utilisation de boucles dans des shells est généralement une mauvaise idée (pas comment les choses se font dans des shells où vous faites fonctionner plusieurs outils collectivement et simultanément à une tâche plutôt que d'exécuter un ou plusieurs outils des centaines de fois dans l'ordre).
Il n'y a pas besoin de substitution de commande si vous souhaitez utiliser le canal:
find . -type f |
while read -r line
do
echo "$line"
done
Bien que comme déjà indiqué, dans le cas de find
vous feriez mieux avec son -exec
option.