41

What does bash - mean in the following bash shell code? It seems to be used to take the output the last code as the input. If so, can I just write it as bash or xargs bash?

curl --silent --location https://rpm.nodesource.com/setup | bash -

2 Answers 2

43

When in doubt, read the source code. =)

Bash 4.3, shell.c line 830, in function 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] == '\0' ||
         (arg_string[1] == '-' && arg_string[2] == '\0')))
    return (next_arg);

In other words, the - is saying that there are no more options. If there were any more words on the command line, they would be treated as a filename, even if the word started with a -.

In your example, of course, that - is completely redundant, as there is nothing following it anyway. In other words, bash - is exactly equivalent to bash.


Bash takes its commands

  1. from a script file if it's provided on the command line, or
  2. non-interactively from its stdin if its stdin is not a TTY (such as in your example: stdin is a pipe, so Bash will execute the contents of that URL as a script), or
  3. interactively if its stdin is a TTY.

It is a misconception that bash - tells Bash to read its commands from its standard input. While it is true that in your example, Bash will read its commands from stdin, it would have done so regardless of whether there was a - on the command line, because, as stated above, bash - is identical to bash.

To further illustrate that - does not mean stdin, consider:

  • The cat command is designed to interpret a - as stdin. For example:

    $ 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
    
  • In contrast, you can't get Bash to execute /bin/date then /bin/hostname by trying this:

    $ echo date | bash - hostname
    /bin/hostname: /bin/hostname: cannot execute binary file
    

    Rather, it tries to interpret /bin/hostname as a shell script file, which fails because it's a bunch of binary gobbledygook.

  • You can't execute date +%s using bash - either.

    $ 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
    

Can you write xargs bash instead? No. curl | xargs bash would invoke bash with the contents of the script as command-line arguments. The first word of the contents would be the first argument, and it would likely be misinterpreted as a script filename.

5
  • 7
    upvote for the only right answer.
    – geirha
    Nov 28, 2015 at 9:41
  • Indeed: in the words of the manpage An argument of - is equivalent to --. Nov 28, 2015 at 14:12
  • If you really, really wanted to use xargs instead, it would work (in the limited scenario of a small enough input script) with | xargs bash -c; but really, this is not a useful or idiomatic use of xargs.
    – tripleee
    Nov 30, 2015 at 6:17
  • @tripleee If the contents of the URL are anything more than a one-liner, then the line breaks and other delimiters would probably be all wrong. Nov 30, 2015 at 6:20
  • Duh, you're right, of course.
    – tripleee
    Nov 30, 2015 at 6:35
1

The intention of the command is to pipe the output from the curl command to bash so it immediately executes commands returned by curl. Basically it tells bash to get its input from stdin. See https://superuser.com/a/1494190/234355

However, there is some discussion about whether this actually works or not in that same answer. If you just execute the first part of the command in the question curl --silent --location https://rpm.nodesource.com/setup, it will output a valid bash script. I didn't try it, not wanting to execute some unknown script from the internet.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .