Dans mon script bash, jutilise find pour obtenir les noms de dossier par joker:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff ${i} done doStuff() { echo ${1} return ${1}"/hello"; }
Le problème est que lorsque je fais cela, jobtiens lerreur suivante (disons que $ {i} correspond à « home / me / my_directory »):
line 111: "/home/me/my_directory": is a directory.
(la ligne 111 est la ligne avec « doStuff « )
Jai essayé de faire ça, en vain:
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard}); do stuff=doStuff "${i}" done
Apparemment, cest parce que le programme essaie dexécuter le répertoire, mais je le veux juste comme une chaîne que je peux manipuler.
Commentaires
Réponse
Les citations et la substitution de commandes sont vos problèmes ici.
Le problème spécifique que vous « rencontrez » est que le shell essaie dexécuter une commande appelée /home/me/my_directory
avec la variable denvironnement stuff=doStuff
.
Ce que vous voulez vraiment (si je » m interprète correctement) est dexécuter doStuff
avec la valeur $i
comme argument, affectant la sortie à la variable stuff
. Pour ce faire, vous devez encapsuler votre commande dans $()
. Par exemple:
stuff="$(doStuff "$i")"
Remarquez comment je mets également des guillemets autour de tout. Cela évite que le shell ne divise par mot les choses que vous ne voulez pas quil « scinde en mot » (il « transformera un seul argument de /foo/bar baz
en /foo/bar
et baz
).
Le résultat de votre fonction est également ce qui est utilisé comme valeur de retour, et non return
.
Comme vous devriez utiliser plus de guillemets, vous devriez également les ajouter à tout le reste. Voici une version complète de votre script:
doStuff() { echo "${1}" >&2 printf "%s/hello" "$1"; } IFS=$"\n" for i in $(find "${directory}" -mindepth 1 -type d -name "${wildcard}"); do stuff="$(doStuff "${i}")" done
Vous devez mettre la définition de la fonction avant dessayer de lutiliser. Shell nest pas analysé comme les programmes compilés, où il parcourt le fichier plusieurs fois. Cest de haut en bas.
Jai également modifié doStuff
pour envoyer le echo
à STDERR où il sera affiché sur le terminal, puis printf
envoie à STDOUT où il sera capturé dans la variable stuff
.
Notez que cela posera toujours un problème si lun de vos répertoires contient une nouvelle ligne. Cependant, il sagit dune limitation du shell. Le seul caractère quun chemin de fichier ne peut pas contient est un caractère NULL (\0
). Cependant, bash et dautres shells ne peuvent pas stocker un caractère NULL dans une chaîne (pas tous, mais beaucoup. Je sais que zsh peut), donc vous pouvez » t lutiliser comme délimiteur.
Commentaires
- Je voulais juste ajouter que si vous avez de lespace avant / après
=
, ça gâche. par exemple. MY_VAR = ' / some / path ' est valide mais MY_VAR = ' / some / chemin ' ou MY_VAR = ' / some / path ' nest pas
Réponse
Cest un bon effort mais cela montre que vous essayez décrire bash
comme sil sagissait dun langage de programmation, alors quil sagit en fait dun simple langage de script. Le problème avec votre construction stuff=doStuff arg
est que bash
ne veut pas dire ce que vous pensez que cela signifie. Pour bash
, stuff=doStuff
est une affectation de variable et arg
est une commande. Je vous suggère de lire les deux liens suivants:
- Comment puis-je stocker la valeur de retour et / ou la sortie dune commande dans une variable?
- Comment renvoyer une chaîne (ou un grand nombre ou un nombre négatif) à partir dune fonction? « return » me permet seulement de donner un nombre compris entre 0 et 255.
Une version fonctionnelle de quelque chose de similaire à ce que vous avez serait
doStuff () { echo "$1/hello" } stuff=$(doStuff "$i")
Réponse
La ligne donnant lerreur ne fait pas ce que vous pensez quelle fait:
Il définit dabord la variable denvironnement stuff sur la chaîne « doStuff », puis essaie dexécuter $ {i} en tant que commande. Et puisque $ {i} est un répertoire, cela échoue avec le message derreur donné.
find "${directory}" -mindepth 1 -type d -name "${wildcard}" -print0 | xargs -0 doStuff
//a wrong bash line comment
au lieu de#a correct bash line comment