The previous part ended with a question: in dir C:\Windows\System32\*.exe, which part is the program and which part is what you tell it to do? dir is the program and everything else is its arguments. Arguments come in different shapes, each with its own rules, and that is what this part is about.
You already know those shapes, because a VFP command like this one has every piece of a console command:
USE customers ALIAS cust EXCLUSIVEUSE is what runs, customers is the thing it works on, ALIAS cust is a clause with its value and EXCLUSIVE is a clause without one. Keep those four in mind, because in the console they are called program, positional, option and flag.
The program and its arguments
Every command starts with the program. What comes after it, separated by spaces, are the arguments:
ping -n 2 127.0.0.1| Piece | What it is |
|---|---|
ping | the program |
-n 2 | an option, -n, with its value, 2 |
127.0.0.1 | a positional argument |
The shell (cmd or PowerShell) splits the line at the spaces, finds the program and hands it the rest. From there on, what each argument means is up to the program. ping knows -n is followed by a number, but another program could use -n for something else. Almost every program follows the conventions in this part, although nothing forces them to.
Positionals: order matters
A positional argument is a bare value with no name in front. The program knows what it is by the place it takes. In ping, the only positional is the machine you ping.
You already do this in VFP every time you call a program with parameters:
DO invoice WITH "B-2026-0042", DATE(), .T.
* and in invoice.prg:
LPARAMETERS tcSeries, tdDate, tlPrintinvoice does not know "B-2026-0042" is the series because of its name, but because it comes first. Swap the order and tcSeries gets a date. The console works the same way: copy source.txt target.txt and copy target.txt source.txt are two very different commands.
Options: a name and, sometimes, a value
An option is an argument with a name. It starts with a dash (or a slash, more on that in a moment) and can carry a value after it:
ping -n 2 127.0.0.1Here -n is the name and 2 its value: how many times to ping. The advantage of the name is that order stops mattering. This does the same:
ping 127.0.0.1 -n 2It is what a clause does in VFP: USE customers ALIAS cust EXCLUSIVE and USE customers EXCLUSIVE ALIAS cust open the table the same way. VFP procedures and functions, on the other hand, have no named parameters: everything goes by position, which is why after the fourth parameter nobody remembers which was which. Options are the console’s way of avoiding that problem.
The value goes right after the name, and the program takes it without looking at what it is. If you forget it:
ping -n 127.0.0.1Debe especificar la dirección IP.That is Spanish for “You must specify the IP address”. ping took 127.0.0.1 as the number of times, and then found itself without an address. Nothing is broken: it did what you told it.
Flags: options without a value
Some options carry no value. They are either there or not, like EXCLUSIVE. They are called flags and they switch a behavior on:
dir /b/b tells dir to list only the names, without dates or sizes. Without /b, you get the usual full listing.
Slash or dash, short or long
You may have noticed that dir uses /b and ping uses -n. That is Windows history: programs that come from MS-DOS use the slash, and almost all the rest (the ones that come from Unix, and nearly every modern tool) use the dash. VFP’s RUN /N belongs to the slash family. ping accepts both, so ping /n 2 127.0.0.1 works too, but do not count on every program doing so.
With the dash there are two forms:
- Short: one dash and one letter,
-n. - Long: two dashes and a word,
--max-count.
Many programs have both for the same option: the short one to type quickly and the long one to be understood when you read it inside a script. With git, for instance, these three commands ask for the same thing, the last change in the history:
git log --oneline -n 1
git log --oneline --max-count=1
git log --oneline --max-count 109f72ae Clientes: altasThe value of a long option can be attached with = or separated by a space. --oneline is a long flag: one line per change.
Subcommands: one program, several jobs
ping does one thing. git does dozens: show the history, save changes, fetch someone else’s. For that it uses subcommands (also called commands or verbs): the first word after the program says which job you want.
git log
git status
git commit -m "Customers: new records"If you think of it as a Fox developer, git is a class and log, status and commit are its methods. Each subcommand has its own options, just as each method has its own parameters: -m in git commit is the change message, and in git log it means something else.
If you type a subcommand that does not exist, the program tells you:
git estadogit: 'estado' is not a git command. See 'git --help'.The same goes for a misspelt option: git log --onelin answers fatal: unrecognized argument: --onelin and does nothing. A well-made console program would rather refuse than guess what you meant.
Quotes: spaces split
The shell splits the line at the spaces, so a name with spaces arrives in pieces. Try this in a test folder:
mkdir My Data
dir /bData
Mymkdir received two arguments and created two folders. With quotes, the shell understands it is one:
mkdir "My Data"My DataThe same happens in VFP with any path that has spaces: DO C:\My programs\sales.prg answers Syntax error and DO "C:\My programs\sales.prg" works. VFP splits at the space too. And with RUN, likewise: if the path of the program or of a file has spaces, it goes in quotes inside the command.
The double dash: options end here
One piece is seldom seen. Two dashes on their own, --, separated from everything, mean “what follows is not options, even if it starts with a dash”.
You need it when a positional looks like an option. Imagine a file called -n (odd, but they exist). Ask git for its history and it takes it for the -n option:
git log --oneline -nerror: -n requires an argumentWith the double dash in front, git knows -n is a file:
git log --oneline -- -nef3e1a1 Fichero con nombre rarogit also uses it to make clear that what follows are files: git log --oneline -- customers.prg shows only the changes that touched that file.
Practice
Open a cmd, create a test folder and go into it:
mkdir C:\cli-tests
cd C:\cli-testsThen, for each command, say which is the program, which are the options (with a value or flags) and which are the positionals. Then run it:
ping -n 1 127.0.0.1
ping 127.0.0.1 -n 1
ping -n 127.0.0.1
mkdir My Data
mkdir "My Data 2"
dir /b
dir /b /ad C:\WindowsThe last one has two flags (/b, and /ad, which asks for folders only) and one positional. On mine it lists 88 folders.
If you type ping on its own, it shows how it is used (the first word is Spanish for “Usage”):
Uso: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
[-r count] [-s count] [[-j host-list] | [-k host-list]]
[-w timeout] [-R] [-S srcaddr] [-c compartment] [-p]With what you have seen today you can already read most of that line: short options, some with a value (-n count) and some without (-t). The brackets and the vertical bar have their own meaning, and reading help like this is what part 4 is for. Before that, in part 3, what a console program writes and where it writes it.