291

I have a directory of ZIP files (created on a Windows machine). I can manually unzip them using unzip filename, but how can I unzip all the ZIP files in the current folder via the shell?

Using Ubuntu Linux Server.

Alex Willison
  • 257
  • 7
  • 20
Lennie De Villiers
  • 5,119
  • 7
  • 31
  • 30
  • for windows in powershell: Get-ChildItem 'path to folder' -Filter *.zip | Expand-Archive -DestinationPath 'path to extract' -Force – Jon Nov 10 '20 at 13:18

17 Answers17

538

This works in bash, according to this link:

unzip \*.zip

Simon Baars
  • 1,877
  • 21
  • 38
ChristopheD
  • 112,638
  • 29
  • 165
  • 179
159

Just put in some quotes to escape the wildcard:

unzip "*.zip"
Brad Koch
  • 19,267
  • 19
  • 110
  • 137
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
  • 2
    +1 This one worked for me. I had to unzip filenames with a particular format while restricting the rest. I just kept the matching format within double quotes and it worked like charm. Output tells me the number of archives successfully processed. – Lalit Kumar B Feb 10 '15 at 05:28
  • 1
    Worked beautifully on Ubuntu for Windows subsystem, 11/18/2018. Top answer didn't work. – julianstanley Nov 18 '18 at 15:41
  • 2
    how can we extract them in directories with their respective names? – Coddy Dec 16 '20 at 00:32
  • 1
    It is important to use quotes or single quotes. Sample: `unzip '*.zip' -d ./myfolder/`. – deadfish Apr 28 '23 at 07:12
113

The shell script below extracts all zip files in the current directory into new dirs with the filename of the zip file, i.e.:

The following files:

myfile1.zip
myfile2.zip 

Will be extracted to:

./myfile1/files...
./myfile2/files...

Shell script:

#!/bin/sh
for zip in *.zip
do
  dirname=`echo $zip | sed 's/\.zip$//'`
  if mkdir "$dirname"
  then
    if cd "$dirname"
    then
      unzip ../"$zip"
      cd ..
      # rm -f $zip # Uncomment to delete the original zip file
    else
      echo "Could not unpack $zip - cd failed"
    fi
  else
    echo "Could not unpack $zip - mkdir failed"
  fi
done

Source Gist


Usage:

cd /dir/with/zips
wget -O - https://www.toptal.com/developers/hastebin/suvefuxuxo.bash | bash
Pedro Lobito
  • 94,083
  • 31
  • 258
  • 268
49

unzip *.zip, or if they are in subfolders, then something like

find . -name "*.zip" -exec unzip {} \;
phatmanace
  • 4,671
  • 3
  • 24
  • 29
  • unzip does wildcard processing so a file called "*.zip" won't do what you expect. – geocar Mar 03 '10 at 20:52
  • 4
    Actually this will do exactly what is expected, the result of the find operation is being passed to unzip – John Bargman Aug 13 '15 at 02:20
  • 4
    This will extract all the zip files in current directory, what if I want the zip files (present in subfolders) to be extracted in the respective subfolders ? – Rishabh Agrahari Feb 16 '18 at 08:44
  • 2
    @RishabhAgrahari I addressed your comment in [a new answer](https://stackoverflow.com/a/49845911/1622937). – j-i-l Apr 15 '18 at 19:26
  • for `gzip'ed` files, use `gunzip -rfk .` for recursive unzipping inside respective folders – Devaroop Mar 13 '19 at 09:49
45

Unzip all .zip files and store the content in a new folder with the same name and in the same folder as the .zip file:

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

This is an extension of @phatmanace's answer and addresses @RishabhAgrahari's comment:

This will extract all the zip files in current directory, what if I want the zip files (present in subfolders) to be extracted in the respective subfolders ?

Saber
  • 2,440
  • 1
  • 25
  • 40
j-i-l
  • 10,281
  • 3
  • 53
  • 70
23
for i in *.zip; do
  newdir="${i:0:-4}" && mkdir "$newdir"
  unzip "$i" -d  "$newdir"
done

This will unzip all the zip archives into new folders named with the filenames of the zip archives.

a.zip b.zip c.zip will be unzipped into a b c folders respectively.

Jahid
  • 21,542
  • 10
  • 90
  • 108
  • This one worked for my use case, needs more up votes. The other approaches do not place the extracted files in a folder of the same name, as expected, but there are some cases where using this approach to separate the folders will be needed. – greg Feb 02 '22 at 20:13
8

In any POSIX shell, this will unzip into a different directory for each zip file:

for file in *.zip
do
    directory="${file%.zip}"
    unzip "$file" -d "$directory"
done
Jeff Fisher
  • 141
  • 1
  • 4
7

aunpack -e *.zip, with atool installed. Has the advantage that it deals intelligently with errors, and always unpacks into subdirectories unless the zip contains only one file . Thus, there is no danger of polluting the current directory with masses of files, as there is with unzip on a zip with no directory structure.

kampu
  • 1,391
  • 1
  • 10
  • 14
  • `aunpack -e -D *.zip` if you want each zip to get its own output dir regardless of the number of files in it (similar to default behavior of ExtractAll in Windows) – teichert Dec 22 '21 at 05:38
5

for file in 'ls *.zip'; do unzip "${file}" -d "${file:0:-4}"; done

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Anurag Dalia
  • 156
  • 4
  • 11
5

If by 'current directory' you mean the directory in which the zip file is, then I would use this command:

find . -name '*.zip' -execdir unzip {} \; 

excerpt from find's man page

-execdir command ;
-execdir command {} +

Like -exec, but the specified command is run from the subdirectory containing the matched file, which is not normally the directory in which you started find. This a much more secure method for invoking commands, as it avoids race conditions during resolution of the paths to the matched files. As with the -exec option, the '+' form of -execdir will build a command line to process more than one matched file, but any given invocation of command will only list files that exist in the same subdirectory. If you use this option, you must ensure that your $PATH environment variable does not reference the current directory; otherwise, an attacker can run any commands they like by leaving an appropriately-named file in a directory in which you will run -execdir.

kaznovac
  • 1,303
  • 15
  • 23
3

Use this:

for file in `ls *.Zip`; do
unzip ${file} -d ${unzip_dir_loc}
done
2

Here is a one liner without using ls that creates folders with the zip names for the files. It works for any zips in the current directory.

for z in *.zip; do unzip "$z" -d "${z%".zip"}"; done

You can add it to your .bashrc

alias unzip_all='for z in *.zip; do unzip "$z" -d "${z%".zip"}"; done'

Inspiration taken from:

Method #2: Unzipping Multiple Files from Linux Command Line Using Shell For Loop (Long Version) in https://www.cyberciti.biz/faq/linux-unix-shell-unzipping-many-zip-files/

dylanmorroll
  • 345
  • 2
  • 12
1

If the files are gzip'd. Then just use:

gunzip -rfk .

from the root directory to recursively extract files in respective directories by keeping the original ones (or remove -k to delete them)

Devaroop
  • 7,900
  • 2
  • 37
  • 34
0

This is a variant of Pedro Lobito answer using How to loop through a directory recursively to delete files with certain extensions teachings:

shopt -s globstar
root_directory="."

for zip_file_name in **/*.{zip,sublime\-package}; do
    directory_name=`echo $zip_file_name | sed 's/\.\(zip\|sublime\-package\)$//'`
    printf "Unpacking zip file \`$root_directory/$zip_file_name\`...\n"

    if [ -f "$root_directory/$zip_file_name" ]; then
        mkdir -p "$root_directory/$directory_name"
        unzip -o -q "$root_directory/$zip_file_name" -d "$directory_name"

        # Some files have the executable flag and were not being deleted because of it.
        # chmod -x "$root_directory/$zip_file_name"
        # rm -f "$root_directory/$zip_file_name"
    fi
done
Evandro Coan
  • 8,560
  • 11
  • 83
  • 144
-1
for i in `ls *.zip`; do unzip $i; done
Dominik
  • 1,194
  • 6
  • 9
-1

Use

sudo apt-get install unzip 

unzip file.zip -d path_to_destination_folder

to unzip a folder in linux

seenukarthi
  • 8,241
  • 10
  • 47
  • 68
Mohit Singh
  • 5,977
  • 2
  • 24
  • 25
-3

To unzip all files in a directory just type this cmd in terminal:

unzip '*.zip'
Mike
  • 1,158
  • 5
  • 22
  • 32