50

When I use tar -xzf *.gz to extract all the .gz files in the current directory, I get Not found in archive error. However, it works fine if I extract one by one or use a for-loop like

for file in `ls *.gz`; do tar -xzf $file; done

What is the reason for this error?

notbad
  • 2,797
  • 3
  • 23
  • 34
  • 2
    it is caused by the fact that argument syntax of tar accept just one single tar in the command line and the rest is interpreted as something else. You could use xargs also (`ls *.gz |xargs -n1 tar -xzf` or alike). – ShinTakezou Jun 05 '13 at 06:47
  • tar do not accept glob pattern as argument (i.e. it won't interpret it) afaik – ShinTakezou Jun 05 '13 at 06:49
  • @ShinTakezou: but the shell will expand the `*.gz` notation; `tar` won't (usually) see the `*.gz`. Sometimes, you want to extract files with the `*` in the name. For example: `tar -xf abc.tar.gz 'src/prog/*name.*'` would extract files such as `src/prog/bigname.c`, `src/prog/smallname.h`; the single quotes prevent the shell from expanding the `*` and `tar` does indeed expand it. – Jonathan Leffler Jun 05 '13 at 07:01
  • @JonathanLeffler I know that ofcourse.In fact,I wrote `tar accepts just one single tar in the command line`,i.e. I imagined the OP thought `tar -xzf *.gz` would work as other cmds accepting more file to work on,but tar interprets `the rest` as something else,i.e. `tar -xzf 1.gz 2.gz 3.gz` would consider only 1.gz as "tar".I missed to specify the expansion of the shell,but it is clear I assumed it.The second comment answered to a now deleted comment saying to escape the `*` (to avoid shell expansion).So I noted that to tar `*.gz` is not a glob pattern,unless it'd interpret it,and afaik it won't – ShinTakezou Jun 05 '13 at 13:53
  • I'm addressing your second comment: _tar do not accept glob pattern as argument (i.e. it won't interpret it) afaik_. AFAICS, that says that you cannot do what I show should work; `tar` _does_ expand glob patterns if requested/required to do so. – Jonathan Leffler Jun 05 '13 at 13:58

3 Answers3

68

When you write

 tar -xzf *.gz

your shell expands it to the string:

 tar -xzf 1.gz 2.gz 3.gz

(assuming 1.gz, 2.gz and 3.gz are in you current directory).

tar thinks that you want to extract 2.gz and 3.gz from 1.gz; it can't find these files in the archives and that causes the error message.

You need to use loop for of command xargs to extract your files.

ls *.gz |xargs -n1 tar -xzf

That means: run me tar -xzf for every gz-file in the current directory.

Elijah Lynn
  • 12,272
  • 10
  • 61
  • 91
Igor Chubin
  • 61,765
  • 13
  • 122
  • 144
42

When you write:

tar -xf *.gz

the tar command sees (for example):

tar -xf abc.tar.gz def.tar.gz ghi.tar.gz

This is interpreted as a request to extract def.tar.gz and ghi.tar.gz from the archive abc.tar.gz. Since the files aren't in there, you get the warning message.

In other words, tar operates on a single tar file (possibly compressed) at a time (in one invocation). It does not operate on multiple tar files.

Note that if abc.tar.gz contains a file pqr/xyz/important.c, you can extract just the one file by specifying:

tar -xf abc.tar.gz pqr/xyz/important.c

The notation you used is only a variant on this notation.

(And yes, there can be reasons to tar a tar file. For example, Gmail does not allow you to ship a tar file or a gzipped tar file which contains a file that is executable. However, if you embed a gzipped tar file inside a non-compressed tar file, it does not look inside the inner file to find the executable file. I use this when I need to ship a tar file with an executable configure script.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
5

the main reason is tar takes a single filename argument. When you are calling tar *.tgz bash extends the * to all file names with tgz formant and it becomes tar file1 file2 file3 which is not accepted by tar. So either you use a for loop like for i in *.tgz; do tar -zxvf $i ;done or use some other command which executes tar as a side effect like shown in comments, is ls or find . -maxdepth 1 -name \*tgz -exec tar -zxvf {} \; (ls output is always risky)

abasu
  • 2,454
  • 19
  • 22