En cas de doute, lisez le code source. =)
shell.c :
/* A single '-' signals the end of options. From the 4.3 BSD sh.
An option '--' means the same thing; this is the standard
getopt(3) meaning. */
if (arg_string[0] == '-' &&
(arg_string[1] == '$ echo xxx | cat /etc/hosts - /etc/shells
127.0.0.1 localhost
xxx
# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
/bin/zsh
/usr/bin/zsh
/usr/bin/screen
/bin/tcsh
/usr/bin/tcsh
/usr/bin/tmux
/bin/ksh93
' ||
(arg_string[1] == '-' && arg_string[2] == '$ echo date | bash - hostname
/bin/hostname: /bin/hostname: cannot execute binary file
')))
return (next_arg);
En d'autres termes, le parse_shell_options()
dit qu'il n'y a plus d'options . S'il y avait plus de mots sur la ligne de commande, ils seraient traités comme un nom de fichier, même si le mot commençait par -
.
Dans votre exemple, bien sûr, -
est complètement redondant, car rien n’y fait suite. En d'autres termes, -
est exactement équivalent à bash -
.
Bash prend ses commandes
- à partir d'un fichier de script s'il est fourni sur la ligne de commande, ou
- de manière non interactive à partir de son stdin si son stdin n'est pas un TTY (comme dans votre exemple: stdin est un canal, Bash exécutera le contenu de cette URL en tant que script) ou
- interactivement si son stdin est un TTY.
Il est faux de croire que bash
dit à Bash de lire ses commandes à partir de son entrée standard. Bien qu'il soit vrai que dans votre exemple, Bash lira ses commandes à partir de stdin, il l'aurait fait qu'il y ait ou non bash -
sur la ligne de commande car, comme indiqué ci-dessus,-
est identique à bash -
.
Pour illustrer davantage que bash
ne signifie pas stdin, considérons:
-
La commande -
est conçue pour interpréter un cat
en tant que stdin. Par exemple:
$ date +%s
1448696965
$ echo date | bash -
Sat Nov 28 07:49:31 UTC 2015
$ echo date | bash - +%s
bash: +%s: No such file or directory
-
En revanche, vous ne pouvez pas obliger Bash à exécuter -
puis /bin/date
en essayant ceci:
/* A single '-' signals the end of options. From the 4.3 BSD sh.
An option '--' means the same thing; this is the standard
getopt(3) meaning. */
if (arg_string[0] == '-' &&
(arg_string[1] == '$ echo xxx | cat /etc/hosts - /etc/shells
127.0.0.1 localhost
xxx
# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
/bin/zsh
/usr/bin/zsh
/usr/bin/screen
/bin/tcsh
/usr/bin/tcsh
/usr/bin/tmux
/bin/ksh93
' ||
(arg_string[1] == '-' && arg_string[2] == '$ echo date | bash - hostname
/bin/hostname: /bin/hostname: cannot execute binary file
')))
return (next_arg);
Il tente plutôt d'interpréter /bin/hostname
en tant que fichier de script shell, ce qui échoue car il s'agit d'un tas de gobbledygook.
-
Vous ne pouvez pas exécuter /bin/hostname
en utilisant date +%s
non plus.
$ date +%s
1448696965
$ echo date | bash -
Sat Nov 28 07:49:31 UTC 2015
$ echo date | bash - +%s
bash: +%s: No such file or directory
Pouvez-vous écrire bash -
à la place? Non, xargs bash
invoquerait bash avec le contenu du script sous forme d'arguments de ligne de commande. Le premier mot du contenu serait le premier argument, et il serait probablement mal interprété comme un nom de fichier de script.