I'm new to working in the shell and the usage of these commands seems arbitrary. Is there a reason one flag has a single dash and another might have a double dash?


5 Answers 5


A single hyphen can be followed by multiple single-character flags. A double hyphen prefixes a single, multicharacter option.

Consider this example:

tar -czf

In this example, -czf specifies three single-character flags: c, z, and f.

Now consider another example:

tar --exclude

In this case, --exclude specifies a single, multicharacter option named exclude. The double hyphen disambiguates the command-line argument, ensuring that tar interprets it as exclude rather than a combination of e, x, c, l, u, d, and e.

  • 24
    Sometimes even long commands can be single-dashed. For example 'cdrecord' uses all single-dashed commands (-eject -dao ...). It all depends on the program, but most(!) of them use - for single and -- for multiple-character (long) commands
    – mulaz
    May 10, 2012 at 14:42
  • 9
    @mulaz, yes, cdrecord does quite a few goofy things.
    – psusi
    May 10, 2012 at 14:46
  • 13
    also bear in mind -- used on its own usually signifys the end of options. see here for more info: unix.stackexchange.com/questions/11376/…
    – Sirex
    May 10, 2012 at 19:51
  • 2
    So why is it java -version and ant -version, then ?
    – killjoy
    Mar 30, 2018 at 14:47
  • 8
    @killjoy, because whether through ignorance or choice, the authors of those programs did not follow the convention of course. Just like cdrecord mentioned years ago in the above comments.
    – psusi
    Apr 2, 2018 at 15:25

It all depends on the program. Usually "-" is used for 'short' options (one-letter, -h), and "--" is used for "long"(er) options (--help).

Short options can usually be combined (so "-h -a" is same as "-ha")

In Unix-like systems, the ASCII hyphen–minus is commonly used to specify options. The character is usually followed by one or more letters. An argument that is a single hyphen–minus by itself without any letters usually specifies that a program should handle data coming from the standard input or send data to the standard output. Two hyphen–minus characters ( -- ) are used on some programs to specify "long options" where more descriptive option names are used. This is a common feature of GNU software.


  • 4
    So why is it java -version and ant -version, then ?
    – killjoy
    Mar 30, 2018 at 14:48
  • @killjoy Because those are no UNIX commands and software developers are free to make their programs follow different rules than those of traditional UNIX commands.
    – Mecki
    Jan 4, 2022 at 0:42

It's really a convention. However, it can aid parsers to know more efficiently about options passed to the program. Besides, there are neat utilities that can help parsing these commands, such as getopt(3) or the non-standard getopt_long(3) to help parse the arguments of a program.

It is nice, for we can have multiple short options combined, as other answers say, like tar -xzf myfile.tar.gz.

If there was a "lisa" argument for ls, there would probably have a different meaning to type ls -lisa than ls --lisa. The former are the l, i, s, and a parameters, not the word.

In fact, you could write ls -l -i -s -a, meaning exactly the same as ls -lisa, but that would depend on the program.

There are also programs that don't obey this convention. Most notably for my sight, dd and gcc.


short options with single dash vs long options with double dash

short options can be combined into a single argument;

for example: ls -lrt #instead of ls -l -r -t

If we allow long options with single dash, it causes ambiguity. To resolve this we use double dash for long options.


Another case is when a script calls another program, it may be necessary to separate the options for the first script from those passed to the second program. For example, you can write a bash function to parse the command line, similar to the function below. Then use a command line similar to the following. In this case the double dashes keep the options for each program separated and allows the built-in parser's error handling to work as intended. Of course, there may special cases that would need to be handled.

 firstscript --firstScriptOption -- --optForSecondProgram
# Parse the command line and set variables to control logic.
parseCommandLine() {
  local additionalOpts exitCode optstring optstringLong
  # Indicate specification for single character options:
  # - 1 colon after an option indicates that an argument is required
  # - 2 colons after an option indicates that an argument is optional, must use -o=argument syntax
  # Indicate specification for long options:
  # - 1 colon after an option indicates that an argument is required
  # - 2 colons after an option indicates that an argument is optional, must use --option=argument syntax
  # Parse the options using getopt command:
  # - the -- is a separator between getopt options and parameters to be parsed
  # - output is simple space-delimited command line
  # - error message will be printed if unrecognized option or missing parameter but status will be 0
  # - if an optional argument is not specified, output will include empty string ''
  GETOPT_OUT=$(getopt --options ${optstring} --longoptions ${optstringLong} -- "$@")
  if [ ${exitCode} -ne 0 ]; then
    # Call a separate function to print usage.
    exit 1
  # The following constructs the command by concatenating arguments:
  # - the $1, $2, etc. variables are set as if typed on the command line
  # - special cases like --option=value and missing optional arguments are generically handled
  #   as separate parameters so shift can be done below
  eval set -- "${GETOPT_OUT}"
  # Loop over the options:
  # - the error handling will catch cases were argument is missing
  # - shift over the known number of options/arguments
  while true; do
    #echo "Command line option is ${opt}"
    case "$1" in
      -h|--help) # Print usage of this script
      --) # No more arguments - following arguments are passed to the second program.
      *) # Unknown option - will never get here because getopt catches up front
        # and remaining options are after --
        echo "Invalid option $1." >&2
        exit 1
  # Get a list of all command line options that do not correspond to dash options:
  # - These are "non-option" arguments after --
  # - For example, one or more file or folder names that need to be processed.
  # - If multiple values, they will be delimited by spaces.
  # - Command line * will result in expansion to matching files and folders.
  shift $((OPTIND-1))
  echo "Additional options: ${additionalOpts}"
  # The additional options would be passed to the second program.
  • this is different, the double hyphen in your example signifies the end of the command options, therefore, anything after it will be interpreted as text (not a command argument). In the example above, the --optForSecondProgram will be interpreted as text or filename (depending on the program). Jul 30, 2021 at 11:08

You must log in to answer this question.

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