59

I have many zip files (a.zip, b.zip, c.zip, ...) and I want to extract each of them into new folders with the same name as the archive's name (a, b, c, ...) via terminal.

Actually, what I want is a solution that I can use later with a find, because I actually have many folders (2014, 2013, 2012, ...) each of which containing many zip files (a.zip, b.zip, ...).

If I do:

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

it will unzip all the files and put them into their respective parent folder.

Michael
  • 725

5 Answers5

95

You should be able to use unzip's -d option to set an alternate directory for the archive contents.

unzip -d a a.zip
unzip -d b b.zip

and so on. Within a find expression, you should be able to derive the name for the directory from the name of the zipfile using shell parameter expansion e.g.

find . -name '*.zip' -exec sh -c 'unzip -d "${1%.*}" "$1"' _ {} \;

Test it first by adding an echo i.e.

find . -name '*.zip' -exec sh -c 'echo unzip -d "${1%.*}" "$1"' _ {} \;

or something like

while read -rd $'\0' f; do 
  unzip -d "${f%.*}" "$f"
done < <(find . -name '*.zip' -print0)
cmcginty
  • 5,888
steeldriver
  • 136,215
  • 21
  • 243
  • 336
44

I came looking for this myself, only to realize I'd already done it with other commands and it could be applied to just about anything else, the way I was already doing it.

The find method is crazy over-complicated for no reason.

for i in *.zip; do unzip "$i" -d "${i%%.zip}"; done
kencinder
  • 539
  • 4
    This is hands down the very best answer to the question at hand. The previous one is ridiculous and the one after this doesn't sort into the files respective root folders. – TheMegolith Mar 06 '19 at 19:56
  • How would one go about creating the directory without the .zip suffix? Asking for a friend. – dashard Apr 15 '19 at 14:37
  • 1
    The answer does not create a directory with a .zip suffix, that is the very point of the portion within the braces. – kencinder Apr 15 '19 at 16:13
  • 1
    Add make directory ${i%%.zip} , for i in *.zip; do mkdir ${i%%.zip}; unzip "$i" -d "${i%%.zip}"; done – Just_Alex Mar 13 '21 at 09:46
  • 1
    Entirely unnecessary to invoke mkdir, that is what the -d flag is already doing. – kencinder Mar 13 '21 at 20:31
  • Here's a comment for anyone (like me) that is a bit rusty on shell subtleties and wants to remember how to do this without looking it up each time. (1) The quotes are important if any of your zip files have spaces in the file name; (2) if you aren't too picky about the resulting directory names, this variant might be easier to remember: for d in *.zip; do unzip "$d" -d "$d.unzipped"; done ; (3) in fact, for some reason, I have a hard time remembering where to put the semi-colons in shell loops, so I usually just press enter after each piece of the loop: header, "do", body, and "done". – teichert May 10 '22 at 23:31
  • mkdir -p might be necessary to create the parent folder. unzip -d can only create one level, the actual target directory. – TWiStErRob Jun 27 '23 at 08:22
6

Simply Use

unzip '*.zip' -d /home/user/folder/
muru
  • 197,895
  • 55
  • 485
  • 740
  • 16
    Unless I'm missing something, this will unzip everything into /home/user/folder, not into /home/user/folder/a and /home/user/folder/b – M. Justin Mar 27 '17 at 19:59
3

I also needed to do this using unrar. This can be achieved by a minor modification to kencinder's code.

for i in *.rar; do mkdir "${i%%.rar}"; unrar x -r "$i" "${i%%.rar}"; done 

PS: I wanted to add this as a comment but I don't have enough reputation points!

0
for z in *.zip; do unar -d "$z"; done
  • 7
    Welcome to AskUbuntu! Could you expand on this answer to explain why someone would want to do this? Generally it's ill advised to blindly run any old code one finds on the Internet – matigo Apr 06 '22 at 13:23