In light of new information I’ve rephrased the question. The old information is below in order to not invalidate answers and comments that were based on it.
I’ve got a tarball tarball.tar I want to extract to destination, a directory that is different from my current working directory, so I use tar’s -C option, which does what I want.
However, if I try to specify files to be extracted from the tarball, the -C option appears to be ignored. The files are extracted in my current working directory.
tar -xf tarball.tar -C destinationTar’s version is
$ tar --version
tar (GNU tar) 1.28Is this a bug or is my understanding of -C wrong?
Minimal Working Example
Here’s a bash script to show the behaviour. Store (or execute) it in an empty directory
#!/bin/bash -x
set -e # Abort if any of these commands fails
touch file1 file2 file3 # Create files to be archived
tar -cf tarball.tar file1 file2 file3 # Create the archive
rm file1 file2 file3 # Remove source files
tar -tf tarball.tar # Should contain files 1–3
mkdir -p destination # Create destination directory
tar -xf tarball.tar file1 file2 -C destination # Extract two files from #+ tarball into destination directory
ls . # Should contain only the script itself, #+ tarball.tar, and destination
ls destination # Should contain file1 and file 2If I execute the script, destination is empty and ls . returns
$ ls .
file1 file2 tarball.tar tar.shIf I do not specify the files to be extracted (sotar -xf tarball.tar file1 file2 -C destinationon line 9 becomestar -xf tarball -C destination)
the behaviour is as expected. ls destination shows file1 file2 file3.
Old Question (ignore this)
I’ve got a tar archive /path/to/backup.tar.gz that contains, among others, the directories home/bleistift2/stuff and home/bleistift2/more_stuff.
In order to extract these two directories to /home/bleistift2/tmp (in the file system, not the archive), I issue the following command. My understanding is that -C specifies the extraction location. The target directory exists.
tar -zxvf /path/to/backup.tar.gz \ # The archive to extract
home/bleistift2/stuff home/bleistift2/more_stuff \ # The contents to extract
--same-owner -C /home/bleistift2/tmp # The destination directoryHowever, the directories are stored as siblings to the archive, so I end up with /path/to/home/bleistift2/{stuff, more_stuff} instead of /home/bleistift2/tmp/home/bleistift2/{stuff, more_stuff}.
2 Answers
-C works literally like cd:
$ tar -tf test.tar
a
b
$ ls -Al dst1/
total 0
$ ls -Al dst2/
total 0
$ tar -xvf test.tar -C dst1/ a -C ../dst2/ b
a
b
$ rm -v dst*/*
removed 'dst1/a'
removed 'dst2/b'
$ (TAR=$(realpath test.tar); cd dst1/; tar -xvf "$TAR" a; cd ../dst2/; tar -xvf "$TAR" b)
a
b
$ rm -v dst*/*
removed 'dst1/a'
removed 'dst2/b'
$So yeah, order matters.
UPDATE: This answer was addressing the issue as understood before the edit of the question, so it turns out it's not an answer to the actual issue reported. I'll delete this answer soon.
The files extracted by tar will contain the full pathname, starting where you begin extraction.
So if the file is stored inside a tarball with name home/bleistift2/stuff and you extract it under /home/bleistift2/tmp/, you'll end up with /home/bleistift2/tmp/home/bleistift2/stuff, since tar has no good way to know you want to strip the home directory prefix during extraction...
You can control this behavior during extraction by passing tar the --strip-components option.
From the tar(1) manpage:
--strip-components=NUMBERstrip NUMBER leading components from file names on extraction
In your specific case:
$ tar -zxvf /path/to/backup.tar.gz \ home/bleistift2/stuff home/bleistift2/more_stuff \ --same-owner -C /home/bleistift2/tmp \ --strip-components=2Stripping 2 components will strip the base home/ directory, plus your user's home directory. Which seems to be what you want, in your specific case.
As a more general advice, try to prevent this issue during creation time, by not storing irrelevant or unwanted parts of the file paths inside the tarball, which can be quite helpful during extraction time.
Instead of using an absolute path (or a full path from the root directory):
$ tar -czvf /path/to/backup.tar.gz /home/bleistift2Change directory to the home directory and pack the current directory instead:
$ cd /home/bleistift2
$ tar -czvf /path/to/backup.tar.gz .That way the files will be stored as ./stuff and ./more_stuff inside the archive, and you won't need to strip any components when extracting it.
You can also use the -C option to change directory, which is equivalent to the above command:
$ tar -czvf /path/to/backup.tar.gz -C /home/bleistift2 . 6