24

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?

4
  • Why copying it in the first place? Why not tar cjf archive.tar.bz2 $MYPATH?
    – Chewie
    May 14, 2013 at 12:37
  • 2
    @Chewie he said, he want the $version as parent dir in archive.
    – Kent
    May 14, 2013 at 12:39
  • Oh, I see it now.
    – Chewie
    May 14, 2013 at 12:45
  • I had a similar problem, and decided to keep coping files. Inefficiency was not critical. --transform gives slightly different archive structure without $VERSION itself. That broke unpacking side, that was not under my control. Dec 11, 2022 at 9:46

4 Answers 4

37

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
2
  • 3
    It is noteworthy that this approach might break symbolic links. Prepending flags=r; solves the problem as mentioned in stackoverflow.com/a/29661783/388803.
    – eregon
    Aug 15, 2017 at 15:35
  • 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. Aug 20, 2018 at 23:42
18

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

tar --transform 's,^\.,$VERSION,' -cf foo.tar .
1
  • This didn't work for me. I found I had to use: tar --transform 's,^,$VERSION/,' -cf foo.tar .
    – IanB
    Jun 24, 2020 at 4:17
1

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.

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.