35

I was wondering whether (and, of course, how) it’s possible to tell tar to extract multiple files in a single run.

I’m an experienced Unix user for several years and of course I know that you can use for or find or things like that to call tar once for each archive you want to extract, but I couldn’t come up with a working command line that caused my tar to extract two .tar.gz files at once. (And no, there’s nothing wrong with for, I’m merely asking whether it’s possible to do without.)

I’m asking this question rather out of curiosity, maybe

  • there’s a strange fork of tar somewhere that supports this
  • someone knows how to use the -M parameter that tar suggested to me when I tried tar -zxv -f a.tgz -f b.tgz
  • we’re all blind and it’s totally easy to do — but I couldn’t find any hint in the web that didn’t utilize for or find or xargs or the like.

Please don’t reply with tar -zxvf *.tar.gz (because that does not work) and only reply with “doesn’t work” if you’re absolutely sure about it (and maybe have a good explanation why, too).

Edit: I was pointed to an answer to this question on Stack Overflow which says in great detail that it’s not possible without breaking current tar syntax, but I don’t think that’s true. Using tar -zxv -f a.tgz -f b.tgz or tar -zxv --all-args-are-archives *.tar.gz would break no existing syntax, imho.

  • Out of curiosity, what is the situation that caused you to start thinking about how to avoid a looping construct? – unclejamil Sep 1 '11 at 2:35
  • 1
    FYI: GNU tar supports multi-volume tar archives with the -M parameter. – Steve-o Sep 1 '11 at 2:49
  • 1
    unclejamil: I’m writing a HowTo and one of the steps in it involves unpacking several compressed files (.tar.bz2, .tar.gz, .zip). And since it’s a HowTo, I was wondering what the most elegant command line to do that would be. :) – scy Sep 1 '11 at 9:45
38

This is possible, the syntax is pretty easy:

$ cat *.tar | tar -xvf - -i

The -i option ignores the EOF at the end of the tar archives, from the man page:

-i, --ignore-zeros
ignore blocks of zeros in archive (normally mean EOF)
  • 1
    This seemed to work for me. Exact command I used was: cat *.tar.bz2 | tar -ixjv. Thanks! – scy Sep 1 '11 at 9:40
  • 1
    <For tgz> cat *.tgz | tar -xzvf - -i -C /destination/ <or> for file in *.tgz; do tar -xzvf $file -C /destination/; done – Ferroao Dec 6 '17 at 13:18
27

for *.tar.gz

for file in *.tar.gz; do tar -zxf "$file"; done

for *.tar.bz2

for file in *.tar.bz2; do tar -jxf "$file"; done

for *.tar.xz

for file in *.tar.xz; do tar -Jxf "$file"; done
  • 1
    Fix the formatting here, and this will be more readable. – eyoung100 Mar 4 '15 at 17:51
  • this is great. the format is also great because thats how it looks in the terminal – smatthewenglish Apr 10 '15 at 11:31
  • 1
    Don't forget to put quotes around $file if your files have names with spaces. – Alexander Revo Dec 1 '16 at 13:22
  • This does not really answer the question of whether it's possible to extract multiple archives using a single invocation of tar. Furthermore, the user says they are already familiar with how to use for-loops to iterate over a set of files. – Kusalananda May 21 '18 at 12:35
2

You need to use a loop. It wouldn't break the tar command line syntax to allow multiple -f options, but it would require adding code to process several archives in sequence, with all kinds of edge conditions (What happens if an archive in the middle is malformed? Can the archives use different compression mechanisms? Can you have multiple -C options (GNU tar option to extract to a particular directory), too? What about -K (GNU tar option to start at a certain member name)? …).

One possibility avoiding a for loop is to install and activate AVFS, a FUSE filesystem that provides transparent access to archives. Each archive /path/to/archive doubles as a directory ~/.avfs/path/to/archive#. If you want to match the archives with wildcards, there's a hurdle of adding that # to a wildcard match; it can be done in zsh.

mountavfs
cp -p ~/.avfs$PWD/{a,b}.tgz\#/* /destination
cp -p ~/.avfs/path/to/source/*.tgz(e\''REPLY=$REPLY\#'\')/* /destination
-1

find . -name "*.tar.gz" -exec tar xzf {} \;

  • what does this do? – Pierre.Vriens May 21 '18 at 12:24
  • 1
    This introduces an implicit loop calling tar once for each found file, and the user says they already know how to do this. – Kusalananda May 21 '18 at 12:25
  • sorry didn't read the question carefully, I was just searching the way to extract multiple tar pack, read the answer above and think use the find will be more easy. – zjengjie May 22 '18 at 6:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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