Unzipping Many ZIP Files

Problem

You want to unzip many ZIP files in a directory, but unzip *.zip doesn’t work.

Solution

Put the pattern in single quotes:

unzip '*.zip'

You could also use a loop to unzip each file:

for x in /path/to/date*/name/*.zip; do unzip "$x"; done

or:

for x in $(ls /path/to/date*/name/*.zip 2>/dev/null); do unzip $x; done

Discussion

Unlike many Unix commands (e.g., gzip and bzip2), the last argument to unzip isn’t an arbitrarily long list of files. To process the command unzip *.zip, the shell expands the wildcard, so (assuming you have files named zipfile1.zip to zipfile4.zip) unzip*.zip expands to unzip zipfile1.zip zipfile2.zip zipfile3.zip zipfile4.zip. This command attempts to extract zipfile2.zip, zipfile3.zip, and zipfile4.zip from zipfile1.zip. That command will fail unless zipfile1.zip actually contains files with those names.

The first method prevents the shell from expanding the wildcard by using single quotes. However, that only works if there is only one wildcard. The second and third methods work around that by running an explicit unzip command for each ZIP file found when the shell expands the wildcards, or returns the result of the ls command.

The ls version is used because the default behavior of bash (and sh) is to return unmatched patterns unchanged. That means you would be trying to unzip a file called /path/to/date*/name/*.zip if no files match the wildcard pattern. ls will simply return null on STDOUT, and an error that we throw away on STDERR. You ...

Get bash Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.