What's the difference between - (one hyphen) and -- (two hyphens) in a command?

Generally:

  • - means to read the argument/content from STDIN (file descriptor 0)

  • -- means end of command options, everything follows that are arguments

Why needed:

About -:

$ echo foobar | cat -
foobar

Although cat can read content from STDIN without needing the -, many commands need that and their man pages mention that explicitly.

Now about --, I have created a file -spam, let's cat the file:

$ echo foobar >-spam  

$ cat -spam         
cat: invalid option -- 'p'
Try 'cat --help' for more information.

$ cat -- -spam      
foobar

Without --, cat takes s, p, a, m all as it's options as they follow -, -- explicitly indicates the end of option(s), after that -spam is taken as a file name.


  • -- is the long name version
  • - is the short name version

Have a look at man ls and some of the options:

-a, --all : do not ignore entries starting with .
-A, --almost-all : do not list implied . and ..
-b, --escape : print C-style escapes for nongraphic characters
-B, --ignore-backups : do not list implied entries ending with ~

They are the same but some prefer the short, some the long versions.

And both are there for compatibility. Removing an option breaks software.


Not every command follows this this. As @ Bakuriu mentions in comment: a command like find has what you can consider "long names" with 1 hyphen.


In regards to coding there is something to note too:

  • Bash's getopts does not support long names.
  • The getopt from the GNU utils does.

This actually depends on the program concerned. There are standards, but they aren't actually enforced anywhere: it's up to each program to implement them.

The find command, for example, takes full name parameters with single hyphens:

find . -iname "*.jpg" -delete

However, in general, double hyphens indicate a switch which is a full word, and single hyphens indicate a swich which is a single letter. And single-letter switches can be combined, which means that all of the following commands are equivalent:

cp --verbose --recursive /dir/from /dir/to
cp -v -r /dir/from /dir/to
cp -vr /dir/from /dir/to

A double hyphen followed by a space can also be used to indicate "this is the end of commands; everything that follows is a file name, even if it looks like a command".

And a single hyphen with no following letters can indicate "read from stdin, not from a file".

However, all of this is program-dependent. Any given program can violate any of these standards, as seen, for example, with find.