Comment échapper à des modèles d'extension des noms de fichiers étendus dans les expressions cités?

StackOverflow https://stackoverflow.com/questions/529054

Question

En plus des * de base, les modèles de ? et [...], la coque Bash fournit aux opérateurs de correspondance de motif étendu comme !(pattern-list) ( « répondant à tous sauf un des motifs donnés »). L'option shell extglob doit être mis à les utiliser. Un exemple:

~$ mkdir test ; cd test ; touch file1 file2 file3
~/test$ echo *
file1 file2 file3
~/test$ shopt -s extglob  # make sure extglob is set
~/test$ echo !(file2)
file1 file3

Si je passe une expression shell à un programme qu'il exécute dans un sous-shell, l'opérateur provoque une erreur. Voici un test qui exécute un sous-shell directement (ici, je suis l'exécution d'un autre répertoire pour faire l'expansion que ne se produise pas prématurément):

~/test$ cd ..
~$ bash -c "cd test ; echo *"
file1 file2 file3
~$ bash -c "cd test ; echo !(file2)"  # expected output: file1 file3
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `cd test ; echo !(file2)'

J'ai essayé toutes sortes d'échapper, mais rien que je suis venu avec a fonctionné correctement. Je soupçonne aussi extglob n'est pas réglé dans un sous-shell, mais ce n'est pas le cas:

~$ bash -c "shopt -s extglob ; cd test ; echo !(file2)"
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `cd test ; echo !(file2)'

Toute solution appréciée!

Était-ce utile?

La solution

$ bash -O extglob -c 'echo !(file2)'
file1 file3

Autres conseils

bash chaque ligne parse avant de l'exécuter, de sorte que « la extglob de shopt » ne sera pas pris effet lorsque bash est la syntaxe de valider englobement modèle. L'option ne peut pas être activée sur la même ligne. Voilà pourquoi la solution (de Randy Proctor) "bash -O extglob -c 'xyz'" fonctionne et est nécessaire.

Voici une autre façon, si vous voulez éviter eval et vous devez être en mesure de tourner extglob sur et en dehors dans le sous-shell. Il suffit de mettre votre modèle dans une variable:

bash -c 'shopt -s extglob; cd test; patt="!(file2)"; echo $patt; shopt -u extglob; echo $patt'

donne cette sortie:

file1 file3
!(file2)

extglob a été mis en et hors service. Si la première echo avait des guillemets autour du $patt, il serait tout simplement cracher le motif comme le deuxième echo (qui devrait probablement les guillemets).

Eh bien, je n'ai pas experince réel avec extglob , mais je peux l'obtenir pour travailler en enveloppant le echo dans un eval:

$ bash -c 'shopt -s extglob ; cd  test ; eval "echo !(file2)"'
file1 file3
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top