7

I have a set of nested zip files and I need to list the file names without extracting the archives. For example:

  • Zip1.zip
    • text1
    • text2
    • Zip2.zip
      • Sample1
      • Sample2

with some shell scripting should result in a list such as

Zip1.zip
Zip1.zip/text1
Zip1.zip/text2
Zip1.zip/Zip2.zip/Sample1
Zip1.zip/Zip2.zip/Sample2
2
  • 1
    how do you expect anything to be able to list the contents of zip2 without extracting it?
    – cas
    Commented Oct 31, 2015 at 5:16
  • Using python following is implemented. i need it in shellscript link
    – Sathish R
    Commented Oct 31, 2015 at 5:36

1 Answer 1

2

The unzip -p flag will pipe the uncompressed data to stdout. Unfortunately the unzip program doesn't have an option to read from stdin for some reason. Adapting the python one liner from this answer to a similar question does the trick.

eg:

unzip -p Zip1.zip Zip1/zip2.zip| python -c 'import zipfile,sys,StringIO;print "\n".join(zipfile.ZipFile(StringIO.StringIO(sys.stdin.read())).namelist())'

Added: The Java jar tool can read from stdin. stolen from this answer.

eg:

unzip -p Zip1.zip  Zip1/zip2.zip| jar -t

output:

zip2/
zip2/Sample2
zip2/Sample1

original zip file:

$ unzip -l Zip1.zip 
Archive:  Zip1.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2015-11-03 15:49   Zip1/
        5  2015-11-03 15:49   Zip1/text1
        5  2015-11-03 15:49   Zip1/text2
      474  2015-11-03 15:48   Zip1/zip2.zip
---------                     -------
      484                     4 files

Found the relevant Serverfault thread from your - comment.


This isn't a shell script, but it does what was suggested in the original question:

#!/usr/bin/python
# Usage: python list-zips.py <zipfile>

import zipfile
import io
import sys

def uz(f, parent=[]):

    result = []
    try:
        zf = zipfile.ZipFile(f)
        for e in zf.namelist():
            path=parent+[e]
            if e.lower().endswith(".zip"):
                result += uz(io.BytesIO(zf.open(e).read()), path)
            else:
                result.append("/".join(path))

    except Exception as ex:
        return result

    return result

print("\n".join(uz(open(sys.argv[1], "rb"), [sys.argv[1]])))

$ python list-zips.py Zip1.zip 
Zip1.zip/text1
Zip1.zip/text2
Zip1.zip/Zip2.zip/Sample1
Zip1.zip/Zip2.zip/Sample2
2
  • 1
    This does not work for nested zip archives or arbitrary nesting depth
    – Jakob
    Commented May 17, 2019 at 16:11
  • Ok, well I added some follow up. I think this might help some folks, as it can be tricky working with archives without writing to disk.
    – jorb
    Commented Jun 12, 2019 at 21:15

You must log in to answer this question.

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