Skip to content
VLSI Mentor

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.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ls -l -h /etc

The 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.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ls   -l      /etc

That 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ls-l /etc
Azvya Education Pvt. Ltd.VLSI Mentor
Representative output
bash: ls-l: command not found

One 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ls -l h

Nothing 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.

Azvya Education Pvt. Ltd.VLSI Mentor
Representative output
ls: cannot access 'h': No such file or directory

The 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

Azvya Education Pvt. Ltd.VLSI Mentor
ls -l -h /etc, decomposed
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 run

Running it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ls -l -h /etc
Azvya Education Pvt. Ltd.VLSI Mentor
Representative output, abbreviated
total 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-release

What each piece produced is visible in the output:

  • without -l this would be a plain list of names, so -l is what added the permissions, owner, size and date columns — the columns Chapter 2.5 will read in full;
  • -h is why the sizes read 4.0K and 1.7K rather than 4096 and 1740;
  • /etc is why you are looking at that directory rather than the working directory;
  • and /etc/os-release is 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ls -l -h /etc
ls -lh /etc

For 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
grep -n error run.log
Azvya Education Pvt. Ltd.VLSI Mentor
Representative output
87:error while loading shared libraries

Decomposed: 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
grep -n -i error run.log
Azvya Education Pvt. Ltd.VLSI Mentor
Representative output
14:ERROR: unable to open device
87:error while loading shared libraries

Note 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.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
grep -ni error run.log

Same 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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:

Azvya Education Pvt. Ltd.VLSI Mentor
sort -k 2 -n data.txt, decomposed
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 name

The 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
grep --line-number --ignore-case error run.log

Identical 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
sort --key=2 data.txt
sort --key 2 data.txt

Two 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.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
dd if=input.bin of=output.bin bs=1M

No 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.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
tail -vn 2 six.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Representative output
==> six.txt <==
e
f

Here -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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
tail -nv 2 six.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Representative output — the exact wording varies between implementations
tail: 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Representative simulator-style arguments — these tools may not exist on your machine
-f filelist.f
+define+DEBUG_ON
+UVM_TESTNAME=smoke_test
-sverilog

A 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
rm -notes.txt
Azvya Education Pvt. Ltd.VLSI Mentor
Representative output — the exact wording varies between implementations
rm: 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
rm -- -notes.txt

Now 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
grep -- -v run.log

That 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:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
du -sh --exclude=build /home/engineer/projects

Work through it structurally, without knowing the tool:

  1. du is the command name — a program to look up (Chapter 1.6).
  2. -sh is a cluster of two short options, s and h, because it has one dash and two letters and neither appears to take a value.
  3. --exclude=build is a long option with an attached value build. Two dashes, a readable name, an =.
  4. /home/engineer/projects has 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 -l means. 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. grep takes 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.