Specify root dir inside tarball

7

Is there a way to execute

tar cjvf foo.tar.bz2 project-root

Such that when the tarball is extracted, it doesn't extract to project-root, but instead extracts to something else? i.e.

tar xjvf foo.tar.bz2
cd something-else
# see all files that were within original project-root

I'm aware of -C, but I want it such that something-else doesn't exist yet.

Pistos

Posted 2010-01-20T01:09:35.243

Reputation: 337

Meaning to say, the extracting user shouldn't have to know what something-else should be (i.e. mkdir it), it's the compressing user that specifies it. – Pistos – 2010-01-20T01:11:26.313

It sounds like you're asking, "If the user extracts the whole archive, create project-root subdirectory. If the user extracts just part of the archive, then call the subdirectory something-else." If not, then just name the directory something-else in the first place. – Stephen Jennings – 2010-01-20T01:50:40.123

Imagine the original directory is called project/, and I want to make tarballs for project-0.1, project-0.2, and so on. Renaming the dir each time doesn't seem optimal. It would be better suited as an option on tar. – Pistos – 2010-01-20T02:40:40.820

yeah. what you're talking about borders on "version control", and is slightly outside tar's scope (which is why there's no option for it). generally if you have a project and want to make a point release, you'd use your version control tools to set certain versions of certain files as project v0.1, or v0.2, etc. then checkout the v0.1 files to a new directory project-0.1, tar that directory, and tahdaaaah, done. – quack quixote – 2010-01-20T02:44:46.600

Answers

4

Make a symlink first, and have tar follow it.

ln -s project-root something-else
tar cjf foo.tar.bz2 something-else/*
rm something-else

The /* is necessary to follow the link and select all the contents rather than just tarring the symlink itself. You could alternatively use the -h option on GNU tar (but this will also follow links inside, which you may not want to do) or the H option on BSD tar (like on a Mac).

You could even do this from inside project-root:

cd project-root
ln -s . something-else
tar cjf foo.tar.bz2 --exclude=something-else/something-else something-else/*
rm something-else

Unless you explicitly exclude it (as above), the symlink will exist in the tarball too.

Obviously if you are doing this lots of times and don't mind the symlink hanging around it doesn't have to be deleted and recreated each time.

tremby

Posted 2010-01-20T01:09:35.243

Reputation: 432

2

You can rename project-root inside the tarball with the 7-zip GUI (and probably other archiver programs as well), but this may do a full decompression-recompression cycle on compressed tarballs. (Read: this may take a while on large, heavily-compressed tarballs.)

The best way to do what you want is to change the name before creating the tarball. A simple way would be to temporarily rename project-root to something-else:

# temporary rename; tar; restore original name
$ mv project-root something-else ; tar cjf foo.tar.bz2 something-else ; mv something-else project-root

I'd probably go a little more complicated: make a copy with the name I want in the tarball. This avoids potential bugs or missed steps in whatever fix-it-up-later process might be employed, and I might want to keep both copies around for other purposes.

# make me a copy
$ ( cd project-root ; tar cf - . ) | ( mkdir something-else; cd something-else; tar xf - )

# test the copy here if needed
$ diff -r --brief project-root/ something-else/

# create my tarball
$ tar cjf foo.tar.bz2 something-else

quack quixote

Posted 2010-01-20T01:09:35.243

Reputation: 37 382

note: if you're looking for this functionality as a means of poor-mans-version-control, you probably want to keep a separate copy of your point release anyway. – quack quixote – 2010-01-20T02:46:08.750

Great answer(s); thanks. Indeed, at the moment, I am doing a multi-command bash chain to compress, decompress, rename and recompress. Your "tar cf - ." solution looks a little better than that, though. – Pistos – 2010-01-20T03:16:55.090

you could probably do the same thing with "cp -a project-root something-else" .. i just automatically reach for the "tar cf - ." one-liner when i need to copy directory trees. been using it so long i can't remember why -- might've been something to do with not understanding all the options to cp. the one-liner's complicated enough that i have to pay attention lest i get something wrong ("tar cf . -" doesn't work so well..) – quack quixote – 2010-01-20T04:19:15.757

Good answer. Maybe the tar -cf - . thing started from making data transfers between machines? of the sort tar cf - . | rsh dest.foo.net 'cd /dest/dir && tar xf -'? – DaveParillo – 2010-01-20T05:10:07.060

@Dave: sure, maybe. it certainly introduced me to the power of chaining commands. – quack quixote – 2010-01-20T05:14:46.007