2

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 destination

Tar’s version is

$ tar --version
tar (GNU tar) 1.28

Is 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 2

If I execute the script, destination is empty and ls . returns

$ ls .
file1 file2 tarball.tar tar.sh

If I do not specify the files to be extracted (so tar -xf tarball.tar file1 file2 -C destination on line 9 becomes tar -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 directory

However, 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}.

4
  • exists the path /home/bleistift2/tmp/ and do you try tar -zxvf /path/to/backup.tar.gz -C /home/bleistift2/tmp
    – SavGuard
    Commented Dec 21, 2019 at 18:34
  • @SavGuard Yes, the target directory exists, and tar does not report an error. Extracting the whole archive works as expected.
    – bleistift2
    Commented Dec 22, 2019 at 4:28
  • 1
    Does this work instead? tar -xf tarball.tar -C destination file1 file2
    – filbranden
    Commented Dec 22, 2019 at 4:48
  • @filbranden Yes, it does. I didn’t think the argument order would matter.
    – bleistift2
    Commented Dec 22, 2019 at 5:22

2 Answers 2

2

-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.

0

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=NUMBER

strip 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=2

Stripping 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/bleistift2

Change 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
  • I didn't pay attention when composing the paths in the question. They're now correcged. The problem I face is not the path prefix in the archive (which is there on purpose), but the wrong target directory. Tar seems to be not changing directories before extractiing.
    – bleistift2
    Commented Dec 21, 2019 at 20:19
  • Right, it seems like @bleistift2’s case is flipped Commented Dec 21, 2019 at 20:44
  • Can't reproduce that, the way you describe it... Do you actually have those comments on the lines and the line continuations? Using -C dir in tar is the same as running cd dir before running tar (if the path to the tarball is absolute), so try that, see if that helps?
    – filbranden
    Commented Dec 21, 2019 at 21:56
  • @filbranden I’ve added an MWE (should’ve done that in the first place). If you execute it, do you get the expected results indicated in the comments?
    – bleistift2
    Commented Dec 22, 2019 at 4:13
  • By any chance... Do you have something like POSIXLY_CORRECT=1 or similar set in your environment? Try to change argument order and move the -C destination earlier in the command-line, see if that makes a difference...
    – filbranden
    Commented Dec 22, 2019 at 4:34

You must log in to answer this question.

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