What does dash "-" at the end of a command mean?

In this case, it means ‘standard input’. It's used by some software (e.g. tar) when a file argument is required and you need to use stdin instead. It's not a shell construct and it depends on the program you're using. Check the manpage if in doubt!

In this instance, standard input is the argument to the -f option. In cases where - isn't supported, you can get away with using something like tar xvf /proc/self/fd/0 or tar xvf /dev/stdin (the latter is widely supported in various unices).

Don't rely on this to mean ‘standard input’ universally. Since it's not interpreted by the shell, every program is free to deal with it as it pleases. In some cases, it's standard output or something entirely different: on su it signifies ‘start a login shell’. In other cases, it's not interpreted at all. Muscle memory has made me create quite a few files named - because some version of some program I was used to didn't understand the dash.


In this case, the - is actually pretty useless, assuming you're running Linux:

GNU tar (the version on Linux) accepts its input from the standard input by default. If you do not want this behaviour, and want to pass the file name as a command line argument, then you need to specify the flag f:

tar xf filename

So this is the same as

tar x < filename

Or, if the input is gzipped as in your example:

gzip -dc filename | tar x

It isn’t meaningful to specify the f flag here at all, but because it was specified, the filename needs to be given as - to indicate that we want to read from standard input (see other answer). So, to repeat, this is redundant and slightly weird.

Furthermore, the above line can be simplified because GNU tar can be told to stream the input through gzip itself by specifying the z flag:

tar xfz filename

– No need to call gzip explicitly.