Em caso de dúvida, leia o código-fonte. =)
Bash 4.3, shell.c
linha 830, em função parse_shell_options()
:
/* 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);
Em outras palavras, o -
está dizendo que não há mais opções . Se houvesse mais palavras na linha de comando, elas seriam tratadas como um nome de arquivo, mesmo que a palavra tenha começado com -
.
No seu exemplo, é claro, que -
é completamente redundante, já que não há nada seguindo isso de qualquer maneira. Em outras palavras, bash -
é exatamente equivalente a bash
.
Bash leva seus comandos
- de um arquivo de script, se fornecido na linha de comando, ou
- não interativamente de seu stdin se seu stdin não for um TTY (como no seu exemplo: stdin é um canal, então o Bash executará o conteúdo desse URL como um script) ou
- interativamente se seu stdin for um TTY.
É um equívoco que bash -
diga ao Bash para ler seus comandos a partir de sua entrada padrão. Embora seja verdade que no seu exemplo, o Bash lerá seus comandos do stdin, isso teria acontecido independentemente de haver -
na linha de comando, porque, como declarado acima, bash -
é idêntico a bash
.
Para ilustrar melhor que -
não significa stdin, considere:
-
O comando
cat
foi projetado para interpretar um-
como stdin. Por exemplo:$ 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
-
Por outro lado, você não pode fazer com que o Bash execute
/bin/date
e/bin/hostname
tentando isso:/* 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] == '
' || (arg_string[1] == '-' && arg_string[2] == '$ 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
'))) return (next_arg);$ echo date | bash - hostname /bin/hostname: /bin/hostname: cannot execute binary file
Em vez disso, ele tenta interpretar
/bin/hostname
como um arquivo de script shell, que falha porque é um monte de gobbledygook binário. -
Você não pode executar
date +%s
usandobash -
.$ 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
Você pode escrever xargs bash
? Não. curl | xargs bash
invocaria o bash com o conteúdo do script como argumentos da linha de comando. A primeira palavra do conteúdo seria o primeiro argumento e provavelmente seria mal interpretada como um nome de arquivo de script.