Commands - Historical Basics
This note contains basics of historical Unix command line syntax. Most of this applies even to this day if nothing else is stated. This explains the "why" behind some of modern command line conventions.
If a program is given unnamed arguments, those were filenames to be used as input.
cat <<EOF > greeting.txt hello world! EOF cat <<EOF > farewell.txt bye you! EOF wc greeting.txt # 1 2 13 greeting.txt wc farewell.txt # 1 2 9 farewell.txt wc *.txt # 1 2 9 farewell.txt # 1 2 13 greeting.txt # 2 4 22 total
The program output would be written to the standard output. This allows chaining or "piping" of commands.
If no filenames were given, it would read the standard input. This is common to this day.
wc # will open a text prompt so you can write your input cat *.txt | wc # 2 4 22 # but now has no knowledge of the filenames as the data was piped through standard input
Single Dash Options
Originally, options always started with a single dash and be a single character. This made parsing simple. The option value could be right after the character or be the next argument.
cat *.txt | sort -r # hello world! # bye you! cat *.txt | sort -k1 # bye you! # hello world! cat *.txt | sort -k2 # hello world! # bye you! cat *.txt | sort -k 2 # hello world! # bye you!
Multiple single character options could be "packed". For example,
-a -b -c could be shortened to foo
cat *.txt | sort -k2r # bye you! # hello world!
Soon it was realized longer option names will be required. For example, if you have
depth which would logically both be
-d, and you will eventually run out of characters in a more complex program.
But this caused:
- Packing became situational as
-depthcould also mean
-h, thus is became responsibility of the program to parse and communicate usage correctly.
- You can't uniformly parse option values without knowing the option names if there is no space between the option name and value e.g.
-depth 1are valid but
-depth1is incorrect (if the 1 is value and not part of the name.)
Double Dash Options
Later, double dash
-- became to communicate a long option. Initially the long option marker was
+ but that is rare to find nowadays.
--help --color auto
Around the same time, equals sign
= became the optional way to specify value. This made creating universal parser much simpler.
Then order of options and other arguments became less strict. Before this, options must've been defined before other arguments (i.e. filenames.)
grep -xi *.txt --regexp=foo --regexp bar # obs. the beginning is expanded to `-x -i`
Double Dash Termination
Empty double dash
-- became to signify "no further options". It was realized that some situations were impossible without a way to terminate options manually.
# if you want to delete a file name `-f` rm -- -f # also useful if you run a program that runs another program with options cargo run -- --version
Subcommands were a simplification of exclusive options. Exclusively checking for e.g.
app --encrypt or
app --decrypt was a bit tedious to both use and validate by the programmer. Using first unnamed arguments as "subcommands" instead of filenames became the norm for early version control software and has since become a standard practice for more complex command line tools.
git --help # show help for the whole `git` git status --help # show help for `status` subcommand git add --help # show help for `add` subcommand