23

When I try to compress files and directories with tar using absolute paths, the absolute path is preserved in the resulting compressed file. I need to use absolute paths to tell tar where the folder I wish to compress is located, but I only want it to compress that folder – not the whole path.

For example, tar -cvzf test.tar.gz /home/path/test – where I want to compress the folder test. However, what I actually end up compressing is /home/path/test. Is there anything that can be done to avoid this? I have tried playing with the -C operand to no avail.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175

5 Answers5

40

This is ugly... but it works...

I had this same problem but with multiple folders, I just wanted to flat every files out. You can use the option "transform" to pass a sed expression and... it works as expected.

this is the expression:

's/.*\///g' (delete everything before '/')

This is the final command:

tar --transform 's/.*\///g' -zcvf tarballName.tgz */*/*.info
  • 8
    This is the only answer I've seen that *actually* does what I'm looking for. – Jonathon Reinhart Dec 09 '14 at 20:18
  • Better result for multiple directories can be achieved in combination with http://serverfault.com/a/566345/343194. Something like `find ./commondir -type f | tar --transform 's/.*\///g' -cvzf ./file.tar.gz --files-from=/dev/stdin`. This way empty child directories will be excluded. – nikolay_turpitko Nov 24 '16 at 05:54
  • Impressive! Found you from the [Materials Modeling stack exchange](https://materials.stackexchange.com/) – Nike Jun 11 '20 at 20:01
  • 1
    Just a note that `--transform` is specific to GNU tar, e.g. in my version (macOS, based on `bsdtar`) the flag `-s '#.*/##g'` worked (I used https://stackoverflow.com/questions/54110172/how-to-escape-chars-in-bsd-tar-path-substitution-option for how to properly escape the `/`). – corwin.amber Nov 02 '22 at 16:00
31

Use -C to specify the directory from which the files look like you want, and then specify the files as seen from that directory:

tar -cvzf test.tar.gz -C /home/path test
Mark Reed
  • 91,912
  • 16
  • 138
  • 175
  • 3
    This still preserves the directory structure *relative* to the specified root directory, which is not what the question appears to be asking (though is apparently what OP needed), but +1 because that's exactly what I was looking for (and the unilateral-flattening approach in the other answer seems like a bizarre thing to want). – Kyle Strand Sep 27 '16 at 21:02
3

multi-directory example

tar cvzf my.tar.gz example.zip -C dir1 files_under_dir1 -C dir2 files_under_dir2

the files under dir 1/2 should not have path.

gigi2
  • 1,996
  • 1
  • 17
  • 22
0

tar can perform transformations on the filenames on the way in and out of the archive. Consider this example that stores a bunch of files in a flat tarfile:

in the root ~/ directory

find logger -name \*.sh | tar -cvf test.tar -T - --xform='s|^.*/||' --show-transformed

The -T - option tell tar to read a list of files from stdin, the --xform='s|^.*/||' applies the sed expression to all the filenames as after they are read and before they are stored. --show-transformed is just a nicety to show you the file names after they are transformed, the default is to show the names as they are read. There are no doubt other ways besides using find to specify files to archive. For instance, if you have dotglob set in bash, you can use ** patterns to wildcard any number of directories, shortening the previous to this:

tar -cvf test.tar --xform='s|^.*/||' --show-transformed logger/**/*.sh

You’ll have to judge what is best for your situation given the files you’re after.

Bala
  • 1
0
find -type f | tar --transform 's/.*\///g' -zcvf comp.tar.gz -T -

Where find -type f finds all the files in the directory tree and using tar with --transform compresses them without including the folder structure. This is very useful if you want to compress only the files that are the result of a certain search or the files of a specific type like:

find -type f -name "*.txt" | tar --transform 's/.*\///g' -zcvf comp.tar.gz -T -

Unlike the other answers, you don't have to include */*/* specifying the depth of the directory. find handles that for you.

Jaime Menendez
  • 1,323
  • 1
  • 9
  • 13