views:

3939

answers:

5

The unzip command doesn't have an option for recursively unzipping archives.

If I have the following directory structure and archives:

/Mother/Loving.zip
/Scurvy/Sea Dogs.zip
/Scurvy/Cures/Limes.zip

And I want to unzip all of the archives into directories with the same name as each archive:

/Mother/Loving/1.txt
/Mother/Loving.zip
/Scurvy/Sea Dogs/2.txt
/Scurvy/Sea Dogs.zip
/Scurvy/Cures/Limes/3.txt
/Scurvy/Cures/Limes.zip

What command or commands would I issue?

It's important that this doesn't choke on filenames that have spaces in them.

+6  A: 

Here's one solution that involves the find command and a while loop:

find . -name "*.zip" | while read filename; do unzip -o -d "`basename -s .zip "$filename"`" "$filename"; done;
chuckrector
A: 

Something like gunzip using the -r flag?....

Travel the directory structure recursively. If any of the file names specified on the command line are directories, gzip will descend into the directory and compress all the files it finds there (or decompress them in the case of gunzip ).

http://www.computerhope.com/unix/gzip.htm

He's specifically talking about zip files, not gzip files.
dvorak
+2  A: 

You could use find along with the -exec flag in a single command line to do the job

find . -name "*.zip" -exec unzip {} \;
Jahangir
This unzips everything into the current directory, rather than relative to each subdirectory. It also doesn't unzip into a directory with the same name as each archive.
chuckrector
I assume that getting the -d right is left as an exercise for the reader. That reader needs to note that -exec only allows one use of {} in the command - get around this by calling sh and assigning {} to a variable.
Steve Jessop
Also note that -execdir is sometimes preferable to -exec. In this case I don't think it will matter.
Steve Jessop
My find (GNU findutils 4.4.0) lets me use {} more than once...cloud@thunder:~/tmp/files$ find . -exec echo {} {} \;. ../a ./a./b ./b./c ./c./d ./d./e ./e./f ./f./g ./g
Sam Reynolds
A: 

If you're using cygwin, the syntax is slightly different for the basename command.

find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done;
A: 

If you want to extract the files to the respective folder you can try this

find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename"`" "$filename"; done;
Vivek Thomas