54
votes

If I choose a zip file and right click "extract here" a folder with the zip filename is created and the entire content of the zip file is extracted into it.

However, I would like to convert several zip files via shell. But when I do

unzip filename.zip

the folder "filename" is not created but all the files are extracted into the current directory.

I have looked at the parameters but there is no such parameter. I also tried

for zipfile in \*.zip; do mkdir $zipfile; unzip $zipfile -d $zipfile/; done

but the .zip extension of the 2. $zipfile and 4. $zipfile have to be removed with sed. If I do

for zipfile in \*.zip; do mkdir sed 's/\.zip//i' $zipfile; unzip $zipfile -d sed 's/\.zip//i' $zipfile/; done 

it is not working.

How do I replace the .zip extension of $zipfile properly?

Is there an easier way than a shell script?

7

7 Answers

60
votes

"extract here" is merely a feature of whatever unzip wrapper you are using. unzip will only extract what actually is in the archive. There is probably no simpler way than a shell script. But sed, awk etc. are not needed for this if you have a POSIX-compliant shell:

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

(You MUST NOT escape the * or pathname expansion will not take place.) Be aware that if the ZIP archive contains a directory, such as with Eclipse archives (which always contain eclipse/), you would end up with ./eclipse*/eclipse/eclipse.ini in any case. Add echo before unzip for a dry run.

88
votes

unzip file.zip -d xxx will extract files to directory xxx, and xxx will be created if it is not there. You can check the man page for details.

The awk line below should do the job:

ls *.zip|awk -F'.zip' '{print "unzip "$0" -d "$1}'|sh

See the test below,

note that I removed |sh at the end, since my zips are fake archives; I just want to show the generated command line here.

kent$  ls -l
total 0
-rw-r--r-- 1 kent kent 0 Nov 12 23:10 001.zip
-rw-r--r-- 1 kent kent 0 Nov 12 23:10 002.zip
-rw-r--r-- 1 kent kent 0 Nov 12 23:10 003.zip
-rw-r--r-- 1 kent kent 0 Nov 12 23:10 004.zip
-rw-r--r-- 1 kent kent 0 Nov 12 23:10 005.zip
-rw-r--r-- 1 kent kent 0 Nov 12 23:10 006.zip
-rw-r--r-- 1 kent kent 0 Nov 12 23:10 007.zip

kent$  ls *.zip|awk -F'.zip' '{print "unzip "$0" -d "$1}'
unzip 001.zip -d 001
unzip 002.zip -d 002
unzip 003.zip -d 003
unzip 004.zip -d 004
unzip 005.zip -d 005
unzip 006.zip -d 006
unzip 007.zip -d 007
9
votes

p7zip, the command line version of 7zip does the job

7z x '*.zip' -o'*'

On debian and ubuntu, you have to install p7zip-full.

8
votes

Add the folder name and slash after the switch, example:

unzip -d newfolder/ zipfile.zip

zip will create the folder 'newfolder' and extract the archive into it.

Note that the trailing slash is not required but I guess it's just from old habit (I use Debian and Ubuntu).

1
votes

aunpack from atool will do this by default for all sorts of archives.

0
votes

In Termux bash I ended up with this, tested for spaces and dots in filenames. It only removes the last file extension and dot for the folder name. This assumes the zip file has a .zip extension otherwise it won't work. Went nuts trying to \ escape the quotes or use single quotes before realizing they just needed to be there as plain quote marks. Drop an echo in front of the zip command, or add a -l to audit the command. For some reason the position of the -d seems important for this implementation.

for f in *.zip; do unzip "$f" \-d "./${f%.*}/"; done; echo -end-
0
votes
  1. Open the terminal and locate the 00* files
cat filename.zip.00* > filename.zip

wait until the process ends, it depends on the file size.

  1. The file joining process finished, now you can run the output file
unzip filename.zip