Prepend prefix in tar

17

5

I currently do in a shellscript very inefficiently:

cp -a $MYPATH /tmp/$VERSION
cd /tmp
tar cjf archive.tar.bz2 $VERSION

I want everything to be contained in the directory called $VERSION - is there a way to do this without having to copy everything as in the above script?

Robby75

Posted 2013-05-14T12:25:56.980

Reputation: 323

Why copying it in the first place? Why not tar cjf archive.tar.bz2 $MYPATH? – Chewie – 2013-05-14T12:37:15.920

2@Chewie he said, he want the $version as parent dir in archive. – Kent – 2013-05-14T12:39:36.353

Oh, I see it now. – Chewie – 2013-05-14T12:45:31.747

Answers

26

The GNU version of tar supports the --transform option (and its alias --xform), you could use it like this

tar --transform "s/^$MYPATH/$VERSION/" -cf archive.tar.bz2 "$MYPATH"

For example, given this directory tree

foo
└── foo.txt

the command

tar --transform "s/^foo/bar/" -cf foo.tar.bz2 foo

will produce an archive like

$ tar -tf foo.tar.bz2
bar/
bar/foo.txt

toro2k

Posted 2013-05-14T12:25:56.980

Reputation: 496

3

It is noteworthy that this approach might break symbolic links. Prepending flags=r; solves the problem as mentioned in https://stackoverflow.com/a/29661783/388803.

– eregon – 2017-08-15T15:35:40.913

don't include a trailing slash; when I put a trailing slash in the transform, the original prefix is missed; eg s/^a\//b\//, the tar -t still shows a/ while all other files are under b/; I assume this is hazardous, and I don't really need to protect against some other file with the same prefix that isn't a directory in the tar file; so no trailing slash is fine, I woudln't mind knowing the best way to handle the case of a/ being transformed but not aa/ if it were a sibling of the root node. – ThorSummoner – 2018-08-20T23:42:01.713

15

To tar the current directory and add a prefix, this worked for me:

tar --transform 's,^\.,$VERSION,' -cf foo.tar .

Andy Balaam

Posted 2013-05-14T12:25:56.980

Reputation: 90

0

To add a directory prefix comfortably, use a different separator than / in the --transform argument, e.g. + or , like in Andy's answer.

So, for a simpler case, you have a bunch of files in current directory, and you don't want to create a tarbomb.

tar czf logs_nightly.tar.gz --tranform 's+^+logs_nightly/+' *.log

The syntax is s+search+replace+, and for ^ it simply matches the start of filename.

And now, just to answer the OP - well, you can avoid copying your whole directory to /tmp by running:

mv $MYPATH $VERSION
tar cjf archive.tar.bz2 $VERSION
mv $VERSION $MYPATH

Alternatively:

ln $MYPATH $VERSION
tar cjf archive.tar.bz2 $VERSION

(hard link, avoids problems with symlinks)

The last two were included for entertainment value, I myself would stick to toro2k's answer.

Tomasz Gandor

Posted 2013-05-14T12:25:56.980

Reputation: 133

0

If you can get away without preserving symbolic links within the file tree you're tarring, you could do

ln -s $MYPATH /tmp/$VERSION
cd /tmp
tar cjhf archive.tar.bz2 $VERSION

The h option means dereference symlinks, i.e. include the file or directory that the link points to rather than simply recording the fact that there was a symlink and what it pointed to.

Ian Roberts

Posted 2013-05-14T12:25:56.980

Reputation: 151