Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

unzip has a nifty option -j, whereby the directory structure of the archive is discarded, and all files are extracted into the same directory.

Is there a way of making tar work in the same way? Nothing in the man page seems to indicate so.

So, is there an alternative, preferably Free Software, tool that will do that?

share|improve this question
    

6 Answers 6

up vote 12 down vote accepted

You can do it fairly easily in two steps. Adapt as necessary:

$ mkdir /tmp/dirtree
$ tar xfz /path/to/archive -C /tmp/dirtree
$ find /tmp/dirtree -type f -exec mv -i {} . \;
$ rm -rf /tmp/dirtree
share|improve this answer
    
this is how i'd do it (using find -exec mv -i instead of find | xargs).... simple steps i can repeat on any system without having to carry around a script to do it for me. –  quack quixote Nov 18 '09 at 5:04
    
+1 simple shot ! –  mate64 Oct 25 '12 at 3:43
    
+1, tmpdir=$( mktemp -d ) is handy when creating temporary directories –  sorki May 22 '13 at 8:12

GNU tar lives on featuritis, so naturally also has some options for that.
http://www.gnu.org/software/tar/manual/html_node/transform.html

If you just want to remove a few path segments, then --strip-components=n or --strip=n will often do:

 tar xvzf tgz --strip=1

But it's also possible to regex-rewrite the files to be extracted (flags are --transform or --xform and accept ereg with the /x modifer):

 tar xvzf tgz --xform='s#^[^/]+#.#x'

For listing a tar you need the additional --show-transformed option:

 tar tvzf tgz --show-transformed --strip=1 --xform='s/abc/xyz/x'

I believe the rewriting options also work for packing, not just for extracting. But pax has obviously a nicer syntax.

share|improve this answer
3  
Why not s#.*/##? –  l0b0 Nov 21 '12 at 13:57
    
--strip just made my day. Thanks! –  SamStephens Dec 2 '12 at 1:33
    
--strip not mentioned in the os x tar man page, but it works anyway, thanks! –  slf Apr 1 at 19:16

pax can do it:

pax -v -r -s '/.*\///p' < archive.tar

or

zcat archive.tar.gz | pax -v -r -s '/.*\///p'

You can check the name replacement operation first by omitting the -r option.

share|improve this answer
    
+1 for pax solution –  Felipe Alvarez Sep 27 '11 at 5:26

A possible solution that doesn't require installing anything.

  1. use a tar tvf to grab all the files from the tarball
  2. Extract those files individually - have tar extract to stdout & redirect to $filename

    tar -tvf $1 | grep -v "^d" | \
                  awk '{for(i=6;i<NF+1;i++) {printf "%s ",$i};print ""}' |\
                  while read filename
                  do
                     tar -O -xf $1 "$filename" > `basename "$filename"`
                  done
    

save as extract.sh and run as extract.sh myfile.tar. It will also overwrite any duplicate filenames encountered in the directories pulled from the tarball.

share|improve this answer
    
Actually I just tested it on some a dir tree at home & It fails on files containing spaces. I'll see if I can't post an update. –  DaveParillo Nov 18 '09 at 0:24
    
Fixed it, but it's not nearly as pretty as it was. –  DaveParillo Nov 18 '09 at 0:39

I used this way:

tar czf archive.tar.gz -C path/to/mydir/ $(ls path/to/mydir/)

tar needs to have all files that are present in the source (distant) directory before changing directory.

If you try to put "*" you will have local files, not the files in distant directory. That's why I provided them with ls.

share|improve this answer
tar xf foo.tar.gz foo/path/to/file/bar.mp3 -O > bar.mp3

The -O option extracts a file to standard out, and > redirects that output into a file. So in my example I'm extracting foo.mp3 and redirecting it into bar.mp3. The file names are arbitrary.

share|improve this answer
    
Could you expand your answer a little to explain this? Thanks. –  fixer1234 Mar 13 at 2:32
    
If I understand this correctly, the user would need to run a command like this for each file in the archive. This doesn't seem to be quite what that question is looking for. Worse, this is similar (but inferior) to the answer posted over five years ago by DaveParillo. –  G-Man Mar 13 at 5:35
    
I disagree with you @G-Man. This is simpler than most other responses provided, and more like the unzip -j option requested. I spent 30 minutes working through some of the responses and finally came up with this one, and it made the build script I was working on MUCH easier. Hopefully it can help someone else looking for something simple and direct. –  Klaatu von Schlacker Mar 13 at 11:20
    
Well, if it's so simple, why don't you respond to fixer1234's request for an explanation? I anticipate seeing an explanation that says, if you have an archive with 100 entries, you have to run tar tf … (or, optionally, tar tfv …) to get a list of the entries, and then run 100 instances of the above command to extract the 100 contained files. If you have a less labor-intensive way of implementing this answer, then that accentuates how inadequate your posted answer is, that we can't figure out how to use it. –  G-Man Mar 13 at 11:30
    
@fixer1234 the -O option extracts a file to standard out, and > redirects that output into a file. So in my example I'm extracting foo.mp3 and redirecting it into bar.mp3. The file names are arbitrary. –  Klaatu von Schlacker Mar 16 at 1:26

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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