6

I am trying to list files in a nested zip as below. It is not listing files in second level.

For example:

abc.zip contains test1.zip, test2.zip, test3.zip

pqr.zip contains test4.zip, test5.zip, test6.zip

for f in *.zip
do
  unzip -l ${f}
  for p in ${f}
  do 
    unzip -l ${p}
  done
done
1
  • That first unzip does nothing (it puts some stuff on the output, but that is not used). The 2nd for iterates over one item. – ctrl-alt-delor Feb 27 at 22:56
2

You can't do it without actually unzipping the top files in a sub-folder.

Something like this:

set -e
for f in *.zip
do
  n=`basename -- "${f}" .zip`
  mkdir -- "${n}"
  cd -- "${n}"
  unzip ../"${f}"
  for p in *.zip
  do
    unzip -l -- "${p}"
  done
  cd ..
  rm -rf -- "${n}"
done

You should probably verify whether ${n} already exists and if so generate an error. You could also use a temporary filename for the sub-directory:

dir=`mktemp -d zip-files.XXXXXX`

Then do cd "${dir}" and rm -rf "${dir}" once done.

Updates:

The set -e is used to make sure that if something goes wrong then the script stops. Especially, if the mkdir -- "${m}" fails, the cd -- "${m}" will fail too and thus the cd .. would get you at the wrong directory level and that's where the rm -rf -- "${n}" becomes dangerous.

Another way to make the cd .. statement safer is to memorize that directory before the for loop and use that path like so:

topdir=`pwd`
for ...
do
  ...
  cd "$topdir"   # instead of `cd ..`
  ...
done

That way the rm -rf -- "${n}" will only operate in $topdir.

The use of the temporary directory will also make things a lot safer since that way whatever the filenames in the top zip file, the directory creation/removal will work as expected.

4
4

With a combination of libarchive's bsdtar and GNU tar, you can list the contents of those nested archives without having to extract them on disk:

for f in *.zip; do
  bsdtar -cf - --include='*.zip' "@$f" | tar -xf - --to-command='bsdtar tvf -'
done

GNU tar can pipe members of archives to commands upon extraction with --to-command but only supports tar archive formats.

bsdtar supports all sorts of archive formats beside tar ones (including zip ones), doesn't have the equivalent of GNU tar's --to-command (AFAIK), but can convert archive formats on the fly.

5
  • In many cases, people do not want to install yet another tool, although this is a nice trick. – Alexis Wilke Feb 27 at 17:16
  • @AlexisWilke, bsdtar is the tool to extract archives. The OP will likely have had to install unzip. bsdtar would have been a much better choice. – Stéphane Chazelas Feb 27 at 17:52
  • unfortunately, bsdtar does not appear to be available in Ubuntu and Arch/Manjaro. – sitaram Feb 28 at 2:03
  • @sitaram It is on Debian based systems including Ubuntu.. Used to be in a bsdtar package; now in libarchive-tools (which now also includes a bsdcpio command). It's becoming a de facto standard. I'd be surprised if any GNU/Linux distribution doesn't at least have a package for it. – Stéphane Chazelas Feb 28 at 7:02
  • @StéphaneChazelas -- indeed, now I found it; thank you for that! I should have searched for the filename instead of package name, earlier. – sitaram Mar 1 at 1:36
2

If GNU Parallel is installed:

extract_list() {
  mkdir "$1"
  cd "$1"
  unzip ../"$1".zip
  parallel unzip -l ::: *.zip
  cd ..
  rm -rf "$1"
}
export -f extract_list

parallel extract_list {.} ::: *.zip

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.