7

I'm trying to make a script that will unzip a password protected file, the password being the name of the file that I will get when unzipping

Eg.

  • file1.zip contains file2.zip and its password is file2.
  • file2.zip contains file3.zip and its password is file3

How do I unzip file1.zip, and read the name of file2.zip so it can be entered in the script?

Here's a screenshot of the command line: Here's a screenshot of what I meant

root@kaliVM:~/Desktop# unzip 49805.zip  
Archive:  49805.zip  
[49805.zip]  13811.zip password:  

I just need Bash to read that output in order to know the new password (In this case the password is 13811).

Here's what I've done so far

#!/bin/bash

echo First zip name:
read firstfile


pw=$(zipinfo -1 $firstfile | cut -d. -f1)
nextfile=$(zipinfo -1 $firstfile)
unzip -P $pw $firstfile

rm $firstfile
nextfile=$firstfile

Now how can I make it do the loop?

10
  • Is it just one file in the initial zipped file and so just file2.zip in file1.zip? Aug 8, 2018 at 12:33
  • Yes, every zip contains a single zip with more than 100 zips in total.
    – molinskeh
    Aug 8, 2018 at 12:39
  • So this is a zip file that's nested 100 levels deep? Or it's one zip file that contains 100 zip files?
    – Jeff Schaller
    Aug 8, 2018 at 13:30
  • (or you have 100 zip files to unzip in the current directory)?
    – Jeff Schaller
    Aug 8, 2018 at 13:32
  • 1
    Is fcrackzip in-scope? If so, don't even bother to ask the user for the file passwords :) Aug 8, 2018 at 20:55

2 Answers 2

9

If you don't have and cannot install zipinfo for any reason, you can imitate it by using unzip with -Z option. To list the contents of the zip use unzip -Z1:

pw="$(unzip -Z1 file1.zip | cut -f1 -d'.')" 
unzip -P "$pw" file1.zip

Put it to a loop:

zipfile="file1.zip"
while unzip -Z1 "$zipfile" | head -n1 | grep "\.zip$"; do
    next_zipfile="$(unzip -Z1 "$zipfile" | head -n1)"
    unzip -P "${next_zipfile%.*}" "$zipfile"
    zipfile="$next_zipfile"
done

or a recursive function:

unzip_all() {
    zipfile="$1"
    next_zipfile="$(unzip -Z1 "$zipfile" | head -n1)"
    if echo "$next_zipfile" | grep "\.zip$"; then
        unzip -P "${next_zipfile%%.*}" "$zipfile"
        unzip_all "$next_zipfile"
    fi
}
unzip_all "file1.zip"

-Z zipinfo(1) mode. If the first option on the command line is -Z, the remaining options are taken to be zipinfo(1) options. See the appropriate manual page for a description of these options.

-1 : list filenames only, one per line. This option excludes all others; headers, trailers and zipfile comments are never printed. It is intended for use in Unix shell scripts.

3
  • Awesome it worked, thank you! Btw in the loop function, why did you grep "\.zip$", head -n1 spits out the same output every time with or without grep. Also what does %%.* mean on the 4th line of the loop function?
    – molinskeh
    Aug 8, 2018 at 13:47
  • 1
    actually %%.* should be %.*, I changed that. See stackoverflow.com/a/965072/7365127 for explanation what it does.
    – pLumo
    Aug 8, 2018 at 13:52
  • | grep "\.zip$" gives same output, but returns true when .zip found and false when not found => As I use it in the if or while statement, this return value will stop the function when ".zip" is not found anymore.
    – pLumo
    Aug 8, 2018 at 13:54
8

Ask zipinfo for the filename listed in the zip file, then capture it for the password. Use that password to unzip the file:

pw=$(zipinfo -1 file1.zip | cut -d. -f1)
unzip -P "$pw" file1.zip

Note that the flag to zipinfo is a one not an ell.

Borrowing liberally from Gilles' answer to a similar question, here's a bash loop that will extract a password-protected nested zip file until there are no more zip files:

shopt -s nullglob
while set -- *.zip; [ $# -eq 1 ]
do 
  unzippw "$1" && rm -- "$1"
done

Where I've defined the function unzippw as a wrapper for the zipinfo and unzip commands above:

unzippw ()
{
    local pw=$(zipinfo -1 "$1" | cut -d. -f1)
    unzip -P "$pw" "$1"
}
5
  • 1
    +1 for zipinfo, didn't know this :->
    – pLumo
    Aug 8, 2018 at 12:57
  • It's part of the unzip package (RPM example, DEB example), so I felt safe suggesting it.
    – Jeff Schaller
    Aug 8, 2018 at 13:09
  • Thanks for the reply, I think I got the logic now, not sure how to continue the loop though
    – molinskeh
    Aug 8, 2018 at 13:28
  • 1
    That loop will only keep the files extracted at the very end which is probably what OP wants, but it's worth mentioning.
    – pLumo
    Aug 8, 2018 at 13:56
  • It won’t even keep the last zip file!
    – Jeff Schaller
    Aug 8, 2018 at 13:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .