19

I am wondering to ask the difference of these two commands (i.e. only the order of their options are different):

  1. tar -zxvf foo.tar.gz
  2. tar -zfxv foo.tar.gz

The first one ran perfectly but the second one said:

tar: You must specify one of the `-Acdtrux' or `--test-label'  options
Try `tar --help' or `tar --usage' for more information.

And tar with --test-label and -zfxv said :

tar (child): xv: Cannot open: No such file or directory
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now

Then I looked at tar manual and realised that all the example there are using switch -f in the end!!

AFAICT there is no need for this restriction, or is there?! because in my view switches should be order free.

4
  • 2
    @schily your "correction" to the command lines obscured what command he actually typed. A leading dash changes GNU tar's behavior to use a different argument parser. Using no dash (and thus the traditional argument parser), the second command would have worked.
    – Random832
    Sep 22, 2015 at 15:33
  • The delta printout from the web system told me that you or someone before added the -, so I removed it again to match what the system told me was from the OP. But if you are right with gtar option parsing, you discovered another reason for not using gtar.
    – schily
    Sep 22, 2015 at 15:52
  • 1
    -f expects the filename to follow. In your second version, you specified -fxv, which - for tar - means that the filename is "xv".
    – Rolf
    Oct 12, 2015 at 11:58
  • 1
    Obligatory XKCD.
    – Pavel
    Oct 28, 2015 at 10:51

4 Answers 4

56

The order of switches is free, but -f has a mandatory argument which is the file that tar will read/write.

You could do

tar -zf foo.tar.gz -xv

and that will work, and has your requirement of a non-specific order of switches.

This is how all commands that have options that have arguments work.

3
  • 5
    Tar does not work like other commands as it uses a different much older command line parser - the same that is used in the "ar" command and the old (pre-POSIX) "ps" command.
    – schily
    Sep 22, 2015 at 14:27
  • 1
    Thank you for this, the selected answer, while thorough, did not really allow me to see what specifically the problem was. In retrospect, it seems obvious from the error message stating tar was trying to read the file 'xv' Sep 22, 2015 at 20:16
  • 1
    I believe you can also declare it as -f=./myfile, that is to say, f takes a value, it isn't a flag, its an input. Sep 22, 2015 at 22:27
14

Traditionally, tar's options are more or less "order-free" (the order of the f and b options do matter if both are specified). Using a leading dash, however, causes GNU tar to parse the options in a way considered more consistent with other commands, where specifying an option that requires an argument (such as the filename for f) will immediately consume the rest of the "word", if any, as the argument (traditionally, tar uses the next word as the filename / block size when f or b is specified). In your case, it took "xv" as the filename.

This behavior cannot be relied on for portability, though. For maximum portability, you should avoid using a dash, always put f last, and always put a space between f and the filename. This is, though, a simplification that breaks down if you need the b option or in general any option (such as C) other than f that requires an argument.

This is documented in the Tar Manual section "The Three Option Styles". Some other implementations (e.g. FreeBSD) refer to the old style options as a "bundled option word". And of course, some implementations may only support this type of option, and may or may not ignore a dash if included. This is the only form of invocation specified in the Single Unix Specification and therefore guaranteed to work on almost all systems.

1
  • 2
    Note that some implementations support other options with arguments (like C in BSD or GNU tar. schily tar supports it as -C but not as C, all support it as -C). Sep 22, 2015 at 15:59
11

Looking at your error message, it is obvious that you did not use tar but rather gtar.

In general this may help to understand things:

  • tar normally always needs a file argument. If it is missing, it will read/write from/to the system's default real tape device. star changed this in 1982 to use stdin/stdout by default and some other tar implementations (e.g. gtar) followed this example recently.

  • tar does not implement the leading - for options that are called key letters in the case of the tar command. Some implementations later added - as a no-op key letter for users' convenience but you cannot rely on this.

  • The way tar parses its arguments (in particular the archive file argument) is highly risky. I have seen many tar archives that destroyed one of the files that should be in the archive because the related file argument was taken as tar archive file. star for this reason (if called natively as star) does not allow "f" to be concatenated with other options. If star is called tar it implements command line compatibility with tar, but still handles the argument for the "f" key letter differently: the argument is only permitted if it refers to a real device file or when (in write mode) the file does not yet exist.

I recommend avoiding the risky original tar command line and rather using the modern safer command line syntax you get with star.

Because of the problematic command line syntax of tar, there were the so called tar wars in the early 1990s. As a result, the program pax (Latin for "peace" in the tar wars) was created and standardized. pax however did not gain popularity as its syntax is less risky but also less intuitive than the tar syntax. Another problem may be that gpax is more or less unmaintained.

15
  • 3
    The tar wars are over. guntar won.
    – Joshua
    Sep 22, 2015 at 15:56
  • 3
    If you were right, why do all tar implementations copy features from star?
    – schily
    Sep 22, 2015 at 16:00
  • 1
    BTW: the tar wars have been a battle between tar and cpio.
    – schily
    Sep 22, 2015 at 16:01
  • 2
    OK, so it seems star's -f"$file" is also (in addition to ind) a problem with file names starting with =. So one needs to write it either -f="$file" or -f "$file". I'm not sure I would call your star option parsing safer or modern. Sep 22, 2015 at 19:10
  • 3
    -long style long options are incompatible with condensed -xyz short options or -xarg. That's why X11 style long options require short options to be separate (-x -y, not -xy) and option arguments to be on separate arguments (xterm -n foo, not xterm -nfoo). And that's why there's an extra dash in GNU long options, to remove the possible confusion with short options, and why GNU-style long options are a better design. You can have -foo coexist with -x -y -xy only if you're very careful to avoid the overlaps. Sep 23, 2015 at 8:36
0

In tar, the - in the switches has been deprecated many years ago and is no longer necessary. Tar actually used to tell you that but no longer does.

ie:
tar zxvf foo.tar.gz
tar zfxv foo.tar.gz

Both of these work fine without the -.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .