29

In this tutorial we need to execute the following command:

# curl -sL https://rpm.nodesource.com/setup_6.x | sudo -E bash -

What does the last - (hyphen) after bash mean?

I've seen a lot of commands with this, and couldn't find myself a logical explanation and neither find how to reformulate a google search for it. Is it the output of the piped command?

4
  • 5
    Same question on Ask Ubuntu — with the same example! Dec 30, 2018 at 3:47
  • 3
    Downloading stuff from the network and piping it directly into sudo bash sounds really scary. Try looking for a tutorial that doesn't encourage such practices. Dec 30, 2018 at 16:43
  • Its the npm tutorial, but i do agree with you... Dec 30, 2018 at 18:01
  • 1
    If you need to search for things with symbols in them, try symbolhound.com.
    – Joe
    Jan 1, 2019 at 5:04

3 Answers 3

39

Bash behaves in somewhat non-standard way when it comes to -.

POSIX says:

Guideline 10:
The first -- argument that is not an option-argument should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the - character.

[…]

Guideline 13:
For utilities that use operands to represent files to be opened for either reading or writing, the - operand should be used to mean only standard input (or standard output when it is clear from context that an output file is being specified) or a file named -.

And

Where a utility described in the Shell and Utilities volume of POSIX.1-2017 as conforming to these guidelines is required to accept, or not to accept, the operand - to mean standard input or output, this usage is explained in the OPERANDS section. Otherwise, if such a utility uses operands to represent files, it is implementation-defined whether the operand - stands for standard input (or standard output), or for a file named -.

But then man 1 bash reads:

A -- signals the end of options and disables further option processing. Any arguments after the -- are treated as filenames and arguments. An argument of - is equivalent to --.

So for Bash - means neither standard input nor a file, hence somewhat non-standard.

Now your particular case:

curl -sL https://rpm.nodesource.com/setup_6.x | sudo -E bash -

I suspect the author of this command may not realize - is equivalent to -- in this case. I suspect the author wanted to make sure bash will read from its standard input, they expected - to work according to the guideline 13.

But even if it worked according to the guideline, - would be unnecessary here because bash detects when its standard input is a pipe and acts accordingly (unless -c is given etc.).

Yet - doesn't work according to the guideline, it works like --. Still -- is unnecessary here because there are no arguments after it.

In my opinion the last - changes nothing. The command would work without it.

To see how -- and - can be useful in general, study the example below.


cat in my Kubuntu obeys both guidelines and I will use it to demonstrate usefulness of - and --.

Let a file named foo exist. This will print the file:

cat foo

Let a file named --help exist. This won't print the file:

cat --help

But this will print the file named --help:

cat -- --help

This will concatenate the file named --help with whatever comes from the standard input:

cat -- --help -

It seems you don't really need --, because you can always pass ./--help which will be interpreted as a file for sure. But consider

cat "$file"

when you don't know beforehand what the content of the variable is. You cannot just prepend ./ to it, because it may be an absolute path and ./ would break it. On the other hand it may be a file named --help (because why not?). In this case -- is very useful; this is a lot more robust command:

cat -- "$file"
0
7

In man bash, at the end of the single-character options there is:-

--    A -- signals the end of options and disables further option processing.
      Any arguments after the -- are treated as filenames and arguments. An
      argument of - is equivalent to --.

If you have quoted the complete command, I can see no reason to use - after bash in this instance, but it does no harm.

3
  • Thank you for your answer, Yes i have quoted the complete command. so anything after - or -- will not be seen as an option but as a file name or arguments, could you please give an example where it is useful ? Dec 28, 2018 at 22:27
  • 1
    It's really to allow for a script whose name begins -, an unlikely requirement, but -/-- makes it possible.
    – AFH
    Dec 28, 2018 at 23:17
  • 1
    @OmarBISTAMI Quoting a command will affect how the shell expands it, but won't affect any of the arguments which follow it. If you extend the quotes around legitimate arguments, then they become part of the command name which isn't what you want either. There are some commands which take file names as arguments, but don't use standard input by default. A contrived example allows you to sandwich input (from a terminal or a pipe) between two files. cat file1 - file2 > file3.
    – Joe
    Jan 1, 2019 at 5:31
5
curl -sL https://rpm.nodesource.com/setup_6.x | sudo -E bash -

bash - means that bash is waiting for stdin. So practically bash will execute whatever is returned by the command that is on the left of |

A similar but easier example would be:

echo hello | cat - here, cat will print 'hello'. Why? Because 'hello' is being sent to cat through | and cat is waiting for anything sent to it

Now let's break the entire command into two:

curl -sL https://rpm.nodesource.com/setup_6.x

this curl command will return something that can be understood and executed by bash

then we have a pipe | which will send the output returned by curl command to to the right side of pipe i.e. sudo -E bash -. Finally in sudo -E bash -, bash is ready to execute anything that is sent to it

You must log in to answer this question.

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