Linux & Bash · Part I · Module 1 · Linux, the Shell and the Command Line
Anatomy of a Command: Words, Options and Arguments
A command line is not a sentence you have to recognise. It has a structure, and once you can see the structure you can take apart a command you have never met and say what each piece is for. This chapter teaches that decomposition, and it is careful about a division of labour that most introductions blur: the shell splits your line into words, and the program you named decides what those words mean. Every surprise in option grammar — and there are many, including in the tools semiconductor engineers use daily — follows from that one division.
Foundation16 min readLinuxBashPart IFundamentalsCommand Line
Part I · Module 1 · Chapter 1.5 · Anatomy of a Command
1. The Shape of a Command Line
A command line is a list of words separated by whitespace. That is the shell's entire view of it.
The first word names what to run. Every word after it is an argument — a word handed to the command. Nothing else is structurally true at the shell's level.
ls -l -h /etcThe shell sees four words: ls, -l, -h, /etc. It takes the first as the thing to run and passes the other three along as a list. Then it steps back.
Everything you are about to learn about options and their values is a statement about what ls does with that list. The shell does not know that -l means anything, and it would pass -l to a program that treats it as a filename just as willingly.
2. Whitespace Is the Separator, and Only That
The amount of whitespace does not matter; its presence does.
ls -l /etcThat is the same three arguments as before. Chapter 1.2 showed why: the shell splits at whitespace and the spacing itself is consumed.
The inverse is where beginners lose time. Remove the space and you have changed the words:
ls-l /etcbash: ls-l: command not foundOne word, ls-l, which names nothing. Note the prefix, exactly as Chapter 1.3 promised: bash: means nothing ran at all.
A subtler version of the same mistake:
ls -l hNothing is wrong with that line syntactically. It asks ls for a long listing of something named h — because h has no leading dash, so ls treats it as an operand rather than an option.
ls: cannot access 'h': No such file or directoryThe prefix is ls: this time. The program ran; it was simply asked about a file that is not there. Two one-character mistakes, two completely different failures, and the prefix tells them apart.
3. Reading One Command Line, Piece by Piece
ls -l -h /etc
│ │ │ └──── operand: what to act on (the directory to list)
│ │ └─────── option: print sizes in human-readable units
│ └────────── option: use the long listing format
└───────────── command name: what to runRunning it:
ls -l -h /etctotal 1.1M
drwxr-xr-x 7 root root 4.0K Mar 14 09:12 apt
-rw-r--r-- 1 root root 1.7K Feb 2 11:40 bash.bashrc
-rw-r--r-- 1 root root 389 Jan 18 08:03 os-releaseWhat each piece produced is visible in the output:
- without
-lthis would be a plain list of names, so-lis what added the permissions, owner, size and date columns — the columns Chapter 2.5 will read in full; -his why the sizes read4.0Kand1.7Krather than4096and1740;/etcis why you are looking at that directory rather than the working directory;- and
/etc/os-releaseis the same file Chapter 1.1 read, now visible as an entry with an owner and a size.
4. Short Options, and Combining Them
An option spelled with a single dash and one letter is a short option. Most commands accept several, and most allow them to be written together:
ls -l -h /etc
ls -lh /etcFor ls, these two lines produce identical output. But the reason is specific, and the task of this section is to make sure you have the reason right.
The shell did not turn -lh into -l -h. The shell passed one argument, the five-character word -lh, to ls. It was ls that looked at that argument, recognised the leading dash, and walked through the remaining letters one at a time.
The practical consequence: when a command rejects an option spelling, the question is never "what does Bash do with this?" It is "what grammar does this program accept?", and Chapter 1.6 is about answering that from the machine in front of you.
5. The Same Grammar on a Different Program
The grammar generalises, which is what makes it worth learning. A different command, read the same way:
grep -n error run.log87:error while loading shared librariesDecomposed: grep is the command name; -n asks for line numbers; error is the first operand and run.log the second.
Only one line came back, and that is worth a moment. The file also contains a line reading ERROR: unable to open device, and it did not match — because grep compares case-sensitively unless told otherwise. Asking for case-insensitive matching is an option:
grep -n -i error run.log14:ERROR: unable to open device
87:error while loading shared librariesNote that the two operands are not interchangeable — grep defines the first as the pattern and the rest as files to search. Position carries meaning for operands in a way it does not for options.
grep -ni error run.logSame thing again, combined, for the same reason as in §4: grep unpacked the letters.
6. Options That Take a Value
Some options need a value. There are two common spellings for a short option, and both are widespread:
sort -k 2 data.txt
sort -k2 data.txt-k asks sort to sort by a particular field, and 2 is which field. In the first form the value is a separate word; in the second it is attached. sort accepts both.
This is where option values cause real confusion, because a value looks exactly like an operand:
sort -k 2 -n data.txt
│ │ │ │ └─────── operand: the file to sort
│ │ │ └────────── option: compare numerically, not as text
│ │ └───────────── option VALUE: belongs to -k, not a file
│ └──────────────── option: sort by a key field
└─────────────────────command nameThe 2 is a word like any other to the shell. Only sort knows that -k consumes the word after it. Read a command line without knowing which options take values and you will misread which words are files.
7. Long Options
A long option is spelled with two dashes and a readable name:
grep --line-number --ignore-case error run.logIdentical in effect to grep -n -i error run.log, and much easier to read later. Long options are the better choice in anything you save: a script using --ignore-case explains itself, while -i has to be looked up.
Long options take values in two spellings:
sort --key=2 data.txt
sort --key 2 data.txtTwo more facts about long options, both practical:
They cannot be combined. --ignore-case --line-number has no shorter form. The combining convention is a short-option convention only.
They are not universal. Long options came largely from the GNU project, so GNU tools have them in abundance; other programs may offer none. A tool that does not document a long form does not have one.
8. Grammars That Do Not Follow the Convention
This is the section that keeps you from being surprised, and the reason this chapter refuses to claim a universal rule.
find uses single-dash, multi-letter tests, and order matters.
find /etc -name os-release -type f-name and -type look like combinable short options and are nothing of the kind: they are multi-letter words after a single dash, each taking a value, in a small expression language of their own. -nt would be meaningless, and the operand /etc must come before the tests. Module 14 teaches find properly; recognising that its grammar is its own is enough here.
dd uses name=value operands with no dashes at all.
dd if=input.bin of=output.bin bs=1MNo options in the conventional sense. Three operands, each a key and a value joined by =. This is a historical interface, preserved because changing it would break decades of scripts.
tar accepts its options with or without a dash.
tar -czf logs.tar.gz logs/
tar czf logs.tar.gz logs/Both work, which is a historical accident rather than a pattern to generalise from — most commands reject options written without a dash.
A clustered option that takes a value must come last. This is not a tar quirk but a consequence of how the standard parsing code works, and it is worth seeing once on a tool where the result is unambiguous. tail -n takes a number:
tail -vn 2 six.txt==> six.txt <==
e
fHere -v is a flag and -n is last in the cluster, so -n claims the following word, 2. Swap the two letters and the value is claimed by the wrong option:
tail -nv 2 six.txttail: illegal offset -- v: Invalid argument-n is no longer last, so what it consumed as its value was the remainder of the cluster — the letter v — and v is not a number. The error names a value you never intended to supply, which is exactly why this class of mistake is confusing on first contact: nothing in the message points at the ordering of the letters.
EDA tools frequently use their own grammar. This is the semiconductor connection, and it needs no chip-design knowledge to appreciate. Simulator command lines routinely look like this:
-f filelist.f
+define+DEBUG_ON
+UVM_TESTNAME=smoke_test
-sverilogA single dash with a multi-letter name; a leading + instead of a dash; a +name=value form. None of these can be combined, and none of them is something Bash understands — Bash splits them into words and passes them on, exactly as it does with -l. Part II works with these in detail. The point for now is that your mental model has to be the one that accommodates them, and "the shell splits, the program interprets" is that model.
9. --: Where the Options Stop
One convention deserves its own section because it solves a real problem.
Create a file whose name begins with a dash and try to remove it:
rm -notes.txtrm: illegal option -- n
usage: rm [-f | -i] [-dIPRrvWx] file ...rm is behaving correctly. It was handed a word starting with a dash and did what programs do with such words: it read the letters after the dash as options, found n, and n is not one of its options.
The convention that fixes this is --, meaning end of options; treat everything after this as operands:
rm -- -notes.txtNow rm stops option parsing at -- and treats the next word as a filename, dash and all. The file is removed and nothing is printed.
The same convention saves a search for text that looks like an option:
grep -- -v run.logThat searches run.log for the literal text -v, rather than being read as grep's -v option.
10. Decomposing Something Unfamiliar
The skill, applied. Here is a command you have not been taught:
du -sh --exclude=build /home/engineer/projectsWork through it structurally, without knowing the tool:
duis the command name — a program to look up (Chapter 1.6).-shis a cluster of two short options,sandh, because it has one dash and two letters and neither appears to take a value.--exclude=buildis a long option with an attached valuebuild. Two dashes, a readable name, an=./home/engineer/projectshas no dash, so it is an operand — the thing being acted on.
That is four correct structural statements about a command you have never run, and the only thing left to look up is what s, h and exclude mean. That is the difference between recognising commands and reading them.
11. Misconceptions
"Bash splits -lh into -l -h." It does not. Bash passes -lh as one word; the program unpacks it. This is the most consequential error in the chapter, because it makes every non-conforming program look broken.
"All Unix commands take options the same way." Most ordinary commands share a convention because they share the same parsing code. find, dd, tar and most EDA tools do not fully share it.
"Anything after the command name is a file." Options and option values are arguments too. sort -k 2 data.txt has one file in it, not two.
"Options must come first." Many GNU programs accept options after operands. Others require strict order — find being the clearest example. There is no universal rule, which is why --help and the manual exist.
"More spaces change the meaning." They do not, as long as there is at least one. Missing or extra dashes change the meaning; extra spaces do not.
12. Check Your Understanding
Question 1. Decompose cp -r --verbose src/ backup/ into command name, options, option values and operands.
Question 2. tail -n 20 run.log — which word is an option value and which is an operand? How many files is tail being asked about?
Question 3. A colleague writes ls -l-h /etc and gets an invalid-option error that names a dash rather than a letter. Explain what the shell passed as one word, and what ls did while reading it.
Question 4. You have a file literally named -f. Write the command that removes it, and say which convention makes it work.
Question 5. Why can --ignore-case and --line-number not be written as --il, when -i and -n can be written as -in?
Question 6. Decompose find . -name core -type f and say why it is not two combinable short options.
13. Remember
- A command line is words separated by whitespace. The first word says what to run; the rest are arguments.
- The shell splits; the program interprets. Bash has no opinion about what
-lmeans. Option grammar belongs to the receiving program. - Short options are one dash and one letter. Combining them is the program's convention, widely implemented because most programs share the same parsing code — not a Bash transformation.
- Some options consume the next word as a value. A value looks exactly like an operand, so you cannot tell which words are files without knowing the options.
- Long options are two dashes and a readable name, cannot be combined, take values with
=or a following word, and are the right choice in anything you keep. - Operand position carries meaning.
greptakes the pattern first and files after; swapping them changes the request. --ends option parsing, which is how you name a file that begins with a dash. A convention, not a law.- Several important grammars do not conform —
find,dd,tar, and most simulator command lines. The model that survives all of them is the one in this chapter.
You can now take a command line apart. The next chapter is how you find out what the pieces mean, from the machine in front of you rather than from a search engine.
Where this fits
Part of the Linux & Bash curriculum.
