Inspired by the recent question Why does the specific sequence of options matter for tar command?, in which the asker learned why tar -cfv test.tar *.jpg
doesn't work, I'd like to ask a followup: seriously, why not?
When a command has an option -f
that requires an argument and an option -v
that doesn't, this:
cmd -fv foo
can be interpreted in 2 different ways: the v
is the argument for the -f
option and foo
is a non-option argument, or foo
is the argument for the -f
option and the -v
option is present. The first interpretation is what POSIX getopt()
does, so there are lots of commands that behave that way.
I always preferred the second interpretation. Packing all the options together (regardless of whether they take arguments) seems more useful than squishing the foo
up against the -f
to turn -f foo
into -ffoo
. But this behavior barely exists anymore. The only command I've used lately that does it is Java's jar
(which has a syntax clearly inspired by that Sun version of tar
which accepts tar cfv tarfile ...
).
Xlib has a getopt
-like function, XrmParseCommand
, which allows options to be specified as either taking "separate" args or "sticky" args. But it deals with long options (-display
, -geometry
, etc.) so it sees -fv
as just another option with no relation to either -f
or -v
. So it's not an example of my second interpretation.
When and why did squished args become dominant? Was it already settled before POSIX, or did the POSIX mandate decide the issue? Did the first version of POSIX even have the same specific requirement as the current version? Is there any archived discussion of the subject from ancient times?
Are there any other commands (besides tar
and jar
) that support or have historically supported the -fv foo
= -f foo -v
style of option parsing?
Best Answer
First of all, in standard
getopt()
-style argument processing, arguments don't have to be squished against the option they apply to, they just can be. So if-f
takes an argument, both of the following are valid:What you call the "second interpretation" is in fact very, very rare. As far as I can think of right now,
tar
andmt
are the only extant commands that works that way... and, as you mention,jar
, but that's only because it emulatestar
. These commands process arguments very differently from the standardgetopt()
-style. The options are not even preceeded by-
! I can't say for sure why it was rarely used, but I would guess that it's because of the fact that it's harder to tell what options go with what arguments. For example, ifb
andd
take arguments buta
,c
, ande
don't, then you have this:...which means that while you are composing the command you have to look back at the option letter group, read it again, remember which options you specified require arguments, and write out the arguments in the same order. What about this?
Oops, the
d
option got theb-argument
and vice versa. Worse, if you see:...and you are not familiar with the command, you have no idea which arguments go with which options.
foo
,bar
, andbaz
might be arguments ton
,o
,p
(andl
andm
take no arguments) orfoo
andbar
might go with, saym
andp
whilebaz
is a positional parameter... or many other possible combinations.