32

I have more than 200 .zip files in one folder. I don't want to decompress those one by one. I want to extract those using single command or script. How to do that.

7 Answers 7

46

If you really want to uncompress them in parallel, you could do

for i in *zip; do unzip "$i" & done

That however, will launch N processes for N .zip files and could be very heavy on your system. For a more controlled approach, launching only 10 parallel processes at a time, try this:

find . -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

To control the number of parallel processes launched, change -P to whatever you want. If you don't want recurse into subdirectories, do this instead:

find . -maxdepth 1 -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

Alternatively, you can install GNU parallel as suggested by @OleTange in the comments and run

parallel unzip ::: *zip
6
  • 3
    Running in parallel is a nice idea, but won't disk I/O be the major bottleneck? Mar 12, 2014 at 13:05
  • 1
    @PaddyLandau not sure, I'd have to check. It will depend on the speed of the decompression algorithm vs the speed of the disk I imagine.
    – terdon
    Mar 12, 2014 at 13:08
  • Use -exec or -execdir instead of piping to xargs. Not only is it simpler to understand, but also it's also less error-prone and uses fewer system resources. find . -name '*.zip' -exec unzip {} ';' (You must quote the semi-colon.) Mar 12, 2014 at 13:10
  • @PaddyLandau the only reason I'm piping to xargs is to run things in parallel as the OP asked. -exec \; (you can escape the semicolon, no need for quotes), will run each command sequentially. -exec + is better but it won't work here since that's not how unzip works.
    – terdon
    Mar 12, 2014 at 13:13
  • I think that we have understood the OP differently. You read him as wanting it in parallel, whereas I understood him as meaning a single command instead of multiple commands. Well, he has both methods now :) Mar 12, 2014 at 21:44
18

The GNU parallel command is well suited to this type of thing. After:

$ sudo apt-get install parallel

Then

ls *.zip | parallel unzip

This will use as many cores as you have, keeping each core busy with an unzip, until they are all done.

17
  • It's a better idea to use echo *.zip instead to prevent a possible ls alias from sneaking in extra info. However, this has the same issue as @Guru's answer, it breaks on file names containing whitespace. Mar 9, 2014 at 13:38
  • 1
    @nyuszika7h In contrast to xargs GNU Parallel does not break on file names containing space/tab/quote. Only if the file names contain newlines you will have to take extra care. For example by using: parallel unzip ::: *.zip
    – Ole Tange
    Mar 9, 2014 at 14:12
  • @nyuszika7h - These are good reasons to avoid both aliasing standard commands, and putting spaces in filenames. Mar 9, 2014 at 15:50
  • @nyuszika7h using echo is as bad as using ls. Globbing and a while loop is the safest.
    – terdon
    Mar 9, 2014 at 15:50
  • 1
    @NateEldredge While that chance was bigger back in the time when systems had only one magnetic disk, these days with RAIDs with multiple spindles and flash disk that chance is smaller. The best thing to do is of course to measure and see how your system behaves. I recently used a 40 spindle RAID where the optimal parallelism for I/O hungry processes was 10: It did not give a 10x speed up - only a 6x, but fewer than 10 processes gave less than 6x.
    – Ole Tange
    Mar 10, 2014 at 8:58
12

You can use the following command :

First change directory in terminal to directory that contains .zip files :

cd /path

Then execute this command to unzip all .zip files :

for z in *.zip; do unzip "$z"; done
10

If you have many .zip files in your folder and you want to decompress all of them then open terminal and go to your folder using:

cd <path_to_folder>

Now use this command to decompress all your .zip file:

ls *.zip | xargs -n1 unzip
5
  • 3
    This will fail if any of the file names contain whitespace.
    – terdon
    Mar 8, 2014 at 20:22
  • 1
    yes, you are correct.
    – g_p
    Mar 8, 2014 at 20:23
  • It's a better idea to use echo *.zip instead to prevent a possible ls alias from sneaking in extra info, however that still does not fix the whitespace issue. Mar 9, 2014 at 13:37
  • 1
    @OleTange In case you didn't notice, I said that it still fails on file names with whitespace in them. Mar 9, 2014 at 15:59
  • 1
    Never depend on the output from ls for scripts, as its output is not well-defined between versions. Instead look at the answer from @terdon as it solves all the problems of this solution. Mar 12, 2014 at 13:04
6

You can use find with -exec like so,

find . -name "*.zip" -exec unzip {} \;

This will work if the file has a space in the name.

3

A non terminal method.

Just select the zip files, right click on one and choose extract here. You can select all or just a number of zip files at a time.

2

unzip \*.zip or unzip '*.zip'

The obvious unzip *.zip doesn't work, because the shell expands it to unzip foo.zip bar.zip ... and unzip interprets the first filename as the zip file, and the following filenames as files to extract from that zip file.

However, unzip is a bit unusual among Unix commands in that it does its own glob expansions. If the * is not expanded by the shell, unzip will do it, and intepret all the resulting filenames as zip files to be processed. So in this special case, one can get away without a for loop or xargs or the like.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .