Pourquoi l'écho appelé en tant que / bin / sh -c écho foo ne produit-il rien?

15

Par exemple, alors que cela fonctionne:

$ echo foo
foo

Cela ne veut pas:

$ / bin / sh -c echo foo

Alors que cela:

$ / bin / sh -c 'echo foo; écho bar '
foo
bar

Y a-t-il une explication?

SilverlightFox
la source

Réponses:

21

De man sh

-c string   If the -c option is present, then commands are read from string. 
            If there are arguments after the string, they are assigned to the
            positional parameters, starting with $0

Cela signifie que votre commande doit être comme ceci:

 $ sh -c 'echo "$0"' foo 
 foo

De même:

$ sh -c 'echo "$0 $1"' foo bar
foo bar

C'était la première partie à comprendre; le deuxième cas est simple et n'a pas besoin d'explication, je suppose.

Ijaz Ahmad Khan
la source
2
Une manière conforme plus stricte et standard seraitsh -c 'echo $1' echo foo
jlliagre
1
sh -c 'echo "$@"' fnord a b c d ...
zwol
3
À mon humble avis, l'explication était assez bonne, mais ce sh -c 'echo $0' foon'est pas la meilleure option, étant donné que l'interrogateur sait déjà que cela /bin/sh -c 'echo foo; echo bar'fonctionne, vous pouvez simplement répondre en citant la commande/bin/sh -c 'echo foo'
X3MBoy
1
@ X3MBoy Le questionneur sait déjà que / bin / sh -c 'echo foo' fonctionne très bien. Il voulait faire écho à quelque chose en dehors de cela, ce que j'ai expliqué
Ijaz Ahmad Khan
18
$ echo foo
foo

Ceci appelle echoavec l'argument foo et foo est imprimé.

$ /bin/sh -c echo foo

Cela invoque le shell avec l'argument echoet fournit foo comme argument $0. Les echosorties une nouvelle ligne et vous jetez le foo . Si vous voulez sortir foo , citez l'argument:

sh -c 'echo foo'

ou utilisez l'argument fourni:

sh -c 'echo $0' foo

Dans cet exemple

$ /bin/sh -c 'echo foo; echo bar'
foo
bar

Le shell est invoqué avec l'argument echo foo; echo barqui génère

foo
bar
Marco
la source
8

Dans cette commande:

echo foo

echoest le binaire (ou la commande intégrée) et fooest le premier argument.

Ici:

/bin/sh -c echo foo

/bin/shest le binaire, dont le premier argument est -c, qui accepte lui-même une "chaîne de commande" comme paramètre. C'est echodans l'exemple ci-dessus. Ensuite, il y a un troisième argument: fooqui est un argument pour /bin/sh, pas pour echo. C'est pourquoi dans votre troisième exemple:

/bin/sh -c 'echo foo; echo bar'

... les deux sont imprimés. Vous avez cité l'argument. Ainsi: le premier argument est -c, et le paramètre de cet argument est 'echo foo; echo bar'qui est interprété entier comme un seul argument; comme "chaîne de commande".

le chaos
la source
3

La structure sh -c wordexécute uniquement le mot (dans un shell).
Les mots ajoutés signifient d'autres choses, comme l'argument zéro, un, deux, etc.:

sh -c word zero one two three

pour garder une commande qui a des espaces comme un seul mot, la citation est nécessaire:

sh -c 'echo fnord' zero one two three

ainsi, cela affiche tous les arguments:

$ sh -c 'echo "args=" "$0" "$@"' zero one two three
args = zero one two three

Exemples

Dans l'exemple que vous présentez: /bin/sh -c echo fooLe premier mot (après les options) est echo, c'est ce qui est exécuté. Et un écho sans texte imprimera une nouvelle ligne uniquement, rien d'autre:

$ / bin / sh -c echo foo

C'est pourquoi vous obtenez une ligne vide.

Si vous citez l'espace, vous exécuterez "un mot" (pas d'espaces), comme ceci:

$ / bin / sh -c echo \ foo
foo
$ / bin / sh -c "écho foo"
foo
$ / bin / sh -c 'echo foo'
foo

Conclusion

Conservez la commande exécutée comme un "mot" en utilisant des guillemets.


la source