web-dev-qa-db-fra.com

Ajouter des arguments à 'Bash -C'

Disons que je veux courir une commande à travers Bash comme ceci:

/bin/bash -c "ls -l"

Selon la page Bash Man, je pourrais aussi l'exécuter comme ceci:

#               don't process arguments after this one
#               |   pass all unprocessed arguments to command
#               |   |
#               V   V
/bin/bash -c ls -- -l

sauf que cela ne semble pas fonctionner (il semble ignoré). Est-ce que je fais quelque chose de mal, ou je n'interprète pas la page de l'homme mal?

Citations pertinentes de l'homme:

Si l'option -c est présente, les commandes sont en lecture de la chaîne. S'il y a des arguments après la chaîne, ils sont attribués aux paramètres de position, en commençant par 0 $.

et

A - signale la fin des options et désactive le traitement supplémentaire des options. Tous les arguments après les - sont traités comme des noms de fichiers et des arguments.

25
Slartibartfast

Vous interprétez la page de l'homme mal. Premièrement, la partie sur -- Signaling La fin des options est hors de propos de ce que vous essayez de faire. Le -c annule le reste de la ligne de commande à partir de ce point de ce point, de sorte qu'il ne traverse plus la gestion des options de Bash, ce qui signifie que le -- serait transmis à la commande , non géré par bash comme marqueur de fin d'options.

La deuxième erreur est que des arguments supplémentaires sont attribués en tant que paramètres de position sur le processus de shell lancé, non passés comme arguments à la commande. Alors, qu'est-ce que vous essayez de faire pourrait être fait comme l'un des suivants:

/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar

Dans le premier cas, passer en écho les paramètres $0 _ et $1 _ _ _ _ explicitement, et dans le second cas, à l'aide de "$@" pour développer comme normal que "tous les paramètres de position sauf" 0 $ ". Notez que dans ce cas, nous devons transmettre quelque chose à utiliser comme $0 aussi; J'ai choisi "Bash" depuis que c'est ce que $0 serait normalement, mais tout ce qui fonctionnerait.

En ce qui concerne la raison, cela est fait de cette façon, au lieu de simplement réussir les arguments que vous donnez directement à la commande que vous listiez: Notez que la documentation indique "Commande -S sont en lecture de la chaîne", pluriel. En d'autres termes, ce schéma vous permet de faire:

/bin/bash -c 'mkdir "$1"; cd "$1"; touch "$2"' bash dir file

Mais notez qu'un meilleur moyen de respecter votre objectif initial pourrait être d'utiliser env plutôt que bash:

/usr/bin/env -- "ls" "-l"

Si vous n'avez besoin d'aucune des fonctionnalités fournies par une coquille, il n'y a aucune raison de l'utiliser - à l'aide de env Dans ce cas, sera plus rapide, plus simple et moins de frappe. Et vous n'avez pas à penser que cela est difficile de vous assurer qu'il gérera en toute sécurité des noms de fichiers contenant des métacarceurs de coquille ou des espaces.

37
godlygeek

Je ne suis pas sûr de votre objectif, mais si vous essayez simplement de construire une Rube Goldberg Machine - "Un contrat d'invention, un dispositif ou un appareil qui est délibérément surdévidé ou trop excédentaire à effectuer une tâche très simple de manière très compliquée "- alors essayez

sh -c 'ls $0' -l

ou

sh -c 'ls $1' supercalifragilisticexpialidocious -l

ou même

sh -c 'ls -$0' l

Vous devriez être capable de comprendre comment ces travaux de la réponse de Godlygeek.

3
Scott