12th Feb 2017
Tar's Force-Local Switch
or Why Can't tar
Cope With Colons?
The Problem
You're probably here because of one of these two error messages:
tar: Cannot connect to hostname: resolve failed tar: hostname:filename: Cannot open: Input/output error
Don't worry, it's easily fixed, with a little bit of understanding of Unix history.
Back in the days of yore...
Back in the old days of Unix, there was a command called "rsh
". If you were around in those days, you will know
it; if you were not, well, it was similar to "ssh
", but without any of the good bits. Basically, you could set up a
file called $HOME/.rhosts
, or a global file named /etc/hosts.equiv
, and any named host (or user:host combination)
would be allowed to log in to your account. They were simpler, more trusting times.
If you want an idea of how old and bad it is note the "BUGS" section on the FreeBSD man page: "The rlogin utility will be replaced by telnet(1) in the near future." So yeah, pretty old. And bad.
Why is this relevant today?
Well, certain implementations of "tar
" were able to use this facility. You could extract an archive from a remote
machine, for example:
john@saturn$ tar -xvf venus:misc/myfiles.tar tar: blocksize = 15 x myfiles, 0 bytes, 0 tape blocks x myfiles/b.txt, 29 bytes, 1 tape blocks x myfiles/e.txt, 29 bytes, 1 tape blocks x myfiles/d.txt, 29 bytes, 1 tape blocks x myfiles/c.txt, 29 bytes, 1 tape blocks x myfiles/f.txt, 29 bytes, 1 tape blocks x myfiles/a.txt, 29 bytes, 1 tape blocks john@saturn$
I must admit, I've not yet managed to find a combination of machines with this awful combination, but it must look 95% like the above.
Why do I care?
The main reason that you are likely to care, is if you are trying to deal with a tar
file with a colon in its name:
$ tar cf my:files.tar * tar: Cannot connect to my: resolve failed $
Or even (with a massive delay as it tries to connect to Google):
$ tar cf google.com:files.tar * ssh: connect to host google.com port 22: Network is unreachable tar: google.com\:files.tar: Cannot open: Input/output error tar: Error is not recoverable: exiting now $
So what tar
is trying to do, is connect to a server called "my
" and create an archive called "files.tar
". In the second case, it's trying to connect to google.com
and create an archive there. That is quite unlikely to succeed, unless you happen to have an rlogin
account on google.com
(hint: Nobody has one of those!)
The Solution
Along with tar
's ability to interpret a "hostname:filename
" argument as a host/file pair, is its "--force-local
" switch, which disables this behaviour.
$ tar --force-local -cf google.com:files.tar *
This tells tar
not to try to be so damned clever, and just take the filename it was given, without trying to convert it into a hostname:filename pair.
Even More Gotchas
Before you think you're out of the woods already; a lot of people have bad habits with tar
syntax, even though they might not realise it.
Most people will either use "tar cvf foo.tar file1 file2
" or "tar -cvf foo.tar file1 file2
".
tar
does nobody any favours by accepting arguments either with or without the "minus". It makes tar
syntax harder to think about.
See, for example, https://xkcd.com/1168/:
So we have to think about the switches. Be very precise. You can combine single-character switches (like "cvf
") together, but
the "f
" is really a "-f filename
" argument. So the two need to go together.
So it's worth being in the habit of using the minuses, and make sure that you keep the "-f
" next to the actual filename that you want tar
to use. For example: "tar -cvf --force-local foo.tar file1 file2
" is not right, because it will attempt to create an archive file called "--force-local
" containing the files foo.tar
, file1
and file2
.
Invest in your career. Buy my Shell Scripting Tutorial today:
og:image credit: Unknown. Please contact me if source is known.