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?
-
1That link is now 404 @cjc :( A possibly more reliable link could be https://en.wikipedia.org/wiki/POSIX – Bernhard Hofmann Mar 15 '18 at 08:16
-
3Better link: https://en.wikipedia.org/wiki/Command-line_interface#Option_conventions_in_Unix-like_systems – Craig Fisher Jul 08 '19 at 18:20
5 Answers
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
.
-
-
1@kylex, no, since there is no long option named just "c" and the -- means a long option, not a single character option follows. – psusi May 10 '12 at 14:37
-
22Sometimes 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 '12 at 14:42
-
9
-
Right, the API for developers for working with command-line parameters under POSIX systems like Linux (and under Windows as well) in C is pretty crappy. Mostly they just expect you to [know the conventions](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02) and manually code your program to conform to them *(made worse by non-standard but common conventions like this one)*, leading to *a lot* of programs that half-conform and have lots of essentially duplicated code. But unfortunately, that's the way things tend to be in C. – BlueRaja May 10 '12 at 15:25
-
@BlueRaja, not so. There is the getopt() api, and the GNU extension: getopt_long(), which is what most apps use these days, and where the double dash comes from. See http://en.wikipedia.org/wiki/Getopt – psusi May 10 '12 at 15:32
-
@psusi: Yes, I am aware of `getopt()` and have used it many times. However, it still leaves conforming to conventions a largely manual process. And `getopt_long()` is not very widely used outside of the built-in Linux utilities, as it is not portable (it's non-POSIX). – BlueRaja May 10 '12 at 16:25
-
13also bear in mind -- used on its own usually signifys the end of options. see here for more info: http://unix.stackexchange.com/questions/11376/what-does-double-dash-mean – Sirex May 10 '12 at 19:51
-
-
2
-
7@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 02 '18 at 15:25
-
1
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.

- 10,472
- 1
- 30
- 37
-
4
-
@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 04 '22 at 00: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
.

- 231
- 1
- 4
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.

- 385
- 5
- 13
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
optstring="h"
# 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
optstringLong="help"
# 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} -- "$@")
exitCode=$?
if [ ${exitCode} -ne 0 ]; then
# Call a separate function to print usage.
printUsage
exit 1
fi
# 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
printUsage
shift
;;
--) # No more arguments - following arguments are passed to the second program.
shift
break
;;
*) # Unknown option - will never get here because getopt catches up front
# and remaining options are after --
echo "Invalid option $1." >&2
printUsage
exit 1
;;
esac
done
# 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))
additionalOpts=$*
echo "Additional options: ${additionalOpts}"
# The additional options would be passed to the second program.
}

- 101
- 1
-
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). – Mousa Halaseh Jul 30 '21 at 11:08