Lorsque les deux lignes de code suivantes sont exécutées dans un script bash, "ls" se plaint que les fichiers n'existent pas:
dirs=/content/{dev01,dev02}
ls -l $dirs
Lorsque j'exécute le script avec l'option -x, il semble que la variable passe entre guillemets simples (ce qui empêcherait la suppression):
+ dirs=/content/{dev01,dev01}
+ ls -l '/content/{dev01,dev01}'
ls: /content/{dev01,dev01}: No such file or directory
Si j'exécute la commande "ls" à partir de mon shell interactif (sans guillemets), les deux répertoires sont renvoyés.
J'ai lu le Manuel de référence de Bash (v 3.2) et je ne vois aucune raison pour que la suppression du nom de fichier ne se produise pas (je ne passe pas -f au shell), globbing arrive.
Je pense que c'est l'ordre des expansions:
L'ordre des extensions est le suivant:
brace expansion
, développement du tilde, paramètre,variable
et expansion arithmétique et substitution de commande (effectuée de la manière suivante: de gauche à droite), Word fractionnement etpathname expansion
.
Donc, si votre variable est substituée, l'expansion d'accolade n'a plus lieu. Cela fonctionne pour moi:
eval ls $dirs
Soyez très prudent avec eval. Il exécutera les choses textuellement. Donc si dirs contient f{m,k}t*; some_command
, une_commande sera exécutée une fois que ls est terminé. Il exécutera la chaîne que vous avez donnée à eval
dans le shell en cours. Il transmettra /content/dev01 /content/dev02
à ls, qu’ils existent ou non. Mettre *
après le truc en fait un chemin d’expansion, et les chemins inexistants seront omis:
dirs=/content/{dev01,dev02}*
Je ne suis pas sûr à 100%, mais cela me semble logique.
Ici est une excellente discussion de ce que vous essayez de faire.
La réponse courte est que vous voulez un tableau:
dirs=(/content/{dev01,dev01})
Mais ce que vous faites avec les résultats peut devenir plus complexe que ce que vous visiez, je pense.
Ce n'est pas une annotation de nom de fichier, c'est une extension d'accolade .. La différence est subtile, mais elle existe - dans cette opération, vous ne recevrez que les fichiers existants, tandis que dans l'expansion d'accolade, vous pouvez générer n'importe quel type de chaîne.
http://www.gnu.org/software/bash/manual/bashref.html#Brace-Expansion
http://www.gnu.org/software/bash/manual/bashref.html#Filename-Expansion
Maintenant, voici ce qui a fonctionné pour moi:
#!/bin/sh
dirs=`echo ./{dev01,dev02}`
ls $dirs
Pour les gens (comme moi) qui trouvent ceci via Google, les réponses de @Peter et @ feoh constituent la solution générale à "Comment globaliser des variables dans un script bash".
list_of_results=(pattern)
sauvegardera les noms de fichiers existants correspondant à pattern
dans le tableau list_of_results
. Chaque élément de list_of_results
contiendra un nom de fichier, des espaces et tous.
Vous pouvez accéder à chaque résultat sous la forme "${list_of_results[<index>]}"
pour <index>
à partir de 0. Vous pouvez obtenir la liste complète correctement citée sous la forme "${list_of_results[@]}"
.
Je suppose que ce dont vous avez besoin est un tableau, mais cela vous limitera à de nouveaux bashes. C'est plus économique que d'utiliser eval.
dirs=( /"content with spaces"/{dev01,dev02} )
dirs=( /content/{dev01,dev02} )
ls -l "${dirs[@]}"
/content/{dev01,dev02}
va s'étendre à:
"/content/dev01" "/content/dev02"
L'existence de ces répertoires est sans rapport avec l'expansion.
Cela devient imprévisible lorsque vous affectez une variable à une extension d'accolade.
dirs=/content/{dev01,dev02}
peut se transformer en
"/content/dev01"
ou
"/content/dev01 /content/dev02"
ou
"/content/dev01" "/content/dev02"
ou
"/content/{dev01,dev02}"
Si vous citez les accolades de quelque manière que ce soit, elles ne s'agrandiront pas. Le résultat contiendra donc les accolades et n'aura pour la plupart aucune signification.
Puisque vous voulez glob files, vous ne devriez pas utiliser de développement d'accolades. Dans ce cas, utiliser l’extension d'accolade est un antipattern et est certainement le mauvais outil pour le travail.
Ce que vous voulez, c'est étendu globbing :
shopt -s extglob # likely already set in interactive shells
dirs=/content/@(dev01|dev02)
ls $dirs
ls `echo $dirs`
travaille sous cygwin.
Le problème que personne n'a abordé est que l'assignation de variable fait la différence.
dirs=/content/{dev01,dev02}
se dilate différemment de
echo /content/{dev01,dev02}
La question est de savoir comment affecter les résultats de l'extension à dirs
Voir: Comment utiliser la substitution Bash dans une déclaration de variable