Here’s a quick tip that will help you work with multiple zip files on the command line.
If you are in a folder and have three zip files in it (a.zip
, b.zip
, c.zip
) that you want to unzip, “no problem,” you think. “I can take care of that with one command.” And you quickly run the following:
[gaarai@tenshi ~]$ unzip *.zip
However, rather than having the unzip program nicely unzip each file one after another, you receive the following:
[gaarai@tenshi ~]$ unzip *.zip Archive: a.zip caution: filename not matched: b.zip caution: filename not matched: c.zip [gaarai@tenshi ~]$
I’m sure that this is not what you were expecting. I know I certainly wasn’t expecting this when I first tried it. However, this problem can help us understand more of how the command line works.
The Problem
Whenever you use a wildcard (*
), the shell itself will expand that and pass the results to the program rather than the program handling the expansion itself. That means that our previous command was actually expanded to the following before being executed:
[gaarai@tenshi ~]$ unzip a.zip b.zip c.zip
Again, this may not look odd since other programs (such as mkdir
, chmod
, etc) can take one or more arguments and repeat the process for each. However, unzip
is different and actually has use for the additional arguments. If you specify additional arguments after the zip file name, unzip
will try to only extract those specific files from the archive rather than all the files.
The previous command told unzip
that it should extract b.zip
and c.zip
from inside the a.zip
archive. Since those files don’t exist inside a.zip
, we get the unexpected error output seen earlier.
You might think that you will have to manually unzip each archive one at a time, but you’d be wrong.
The Solution
Just because the shell expands out wildcard characters automatically doesn’t mean that programs can’t as well. The simple solution to this problem is to quote the argument to prevent the shell from interpreting it:
[gaarai@tenshi ~]$ unzip '*.zip' Archive: c.zip creating: c/ inflating: c/test.txt Archive: a.zip creating: a/ inflating: a/test.txt Archive: b.zip creating: b/ inflating: b/test.txt 3 archives were successfully processed. [gaarai@tenshi ~]$
That’s all there is to it. I’ve seen solutions from coding loops in bash script to running find combined with xargs
, but none of that is necessary. Simply let the unzip
command itself take care of things for you.
Did I help you?
Thanks for the tip. I was handing my head trying to figure out why I kept getting the ‘caution’ message.
It is a bit unintuitive, but we just have to think like a command line. 🙂
Thank you! I downloaded 397 zip files (recipes) that i wanted to extract and import into gourmet recipe manager…Thanks again!!!
You’re welcome Rob.
hi very nice tip thx
but a question??
what if???? a.zip b.zip c.zip have a password and the password it’s the same for all the files example: “one”
I tried: unzip ‘*.zip’ -P one
but didn’t works so there’s a way to solved???
thnxs for your time 🙂
That’s because you are reversing the order of your command arguments. The options (
-P pass
) go first. The file listing goes last.So, the correct command is
unzip -P pass '*.zip'
.Great tip , Thank’s
I just wanted to let you know that, two and a half years later, this page is still helping people. It certainly helped me. I have been working with a weekly Salesforce dump for several weeks now, consisting of 14 zip files.
I had just been typing out the stuff manually, then changing the 1, 2, 3, etc. near the end before .ZIP and running them all together with a ;.
Tonight I said, “enough!” and googlized it. I found your page. The palm of my hand impacted my forehead at the simplicity of it. So, thanks for posting this and keeping it up here. Surf Wisely!
Glad to hear dolst. 🙂
Thanks for the very clear explanation..
Good catch. I had the same issue and this helped me solve it.
Thanks! this totally worked
Great tip. One remark – you use curly single quotes in the example, probably because of you rich text editor. That won’t work. You need the normal quotes.
Unfortunately, WordPress likes to change quotes into “smart quotes”. I’ve updated the post to use the format I use now.
Thanks for pointing out the issue.
Hello,
The somple quote Solution doesn’t work for me.
I used this command line ans it works pretty well:
for z in *.zip; do unzip $z; done
Best Regards,
Tarik Farajallah
That is strange. Perhaps the difference is due to keyboard language. What happens when you try to use the quotes? Are any errors shown?
Great tip. It also applies to unrar and 7z.
what should be the command if I want to unzip files which are not like a given format: unzip not like *MTH*
I’m not sure what you are asking. Is “unzip not like *MTH*” an error you receive? If so, I’ve never seen such an error.
How smart was that developer who programmed that
unzip *.zip
and
unzip ‘*.zip’
work differently.
As explained in the post, the shell expands the * before running the command. Thus, the command never sees
*.zip
and instead only sees the resulting expanded argument list. For nearly every command, this does not create an issue, but it does for thezip
command due to how it structures its argument list and thus requires quoting the argument to prevent shell expansion.So simple, yet so effective… Really like the way you explain things.
You tip saved me a lot of effort. Thank you so much!!
Thank!
Faster than the man page! 😀
thanks.
Really Appreciate the Help !
Keep Up the Good Work ! (Y) 😀
Thanks so much! I was beating my head against the wall for a half an hour before finding this answer! Peace be with you!
Thanks you so much bro..
Short and Simple
Thanks:)
Great tip, thank you!
I’ve thought it’s Win LFN with spaces issue, but 🙂
You’re amazing. This just saved me TONS of time.
[…] Unzip Multiple Files from Linux Command Line […]
thank you!!
In a folder with a.zip, b.zip and c.zip, how can I only unzip a.zip and b.zip? Thanks.
unzip '[ab].zip'
You can find full details in the man page for the unzip command. While this example looks like a regular expression, the unzip command only supports a few regex-like patterns, so reading the man page is critical to understanding what options you have. Keep in mind to always quote the file parameter as many shells also interpret these patterns.
Thanks man! That was really helpful! Great tip.
Stay awesome.
Wow! Thank’s man!
Right now I wanted to write a loop for this purpose 🙂