Move required files where they need to go
Question: I'm working on a Python script that unzips a compressed directory and installs
some files. When you unzip the compressed file, there could be files like
`./usr/bin/package` or `./var/lib/package`. The unzipped directory contains
the names of the dirs where they actually need to go. Lets say the directory
structure looks like:

    
    
    ./zippedfile.zip
    ./usr
        /bin
            /package
    ./var
        ./lib
            ./package
    

` Now I need to move the required files where they need to go. For example I
need to move `./usr/bin/package` to the actual `/usr/bin/` directory. Thing
is, it's not predictable which folders there may be, so the script needs to
find the required directories and move them. Thanks, hopefully I made the
question clear.


Answer: Use the zipfile module to read the zip file and `extract(name, dest)` to
extract each file. For example:

    
    
    import sys
    import zipfile
    
    def unzip(path, root='/'):
        zh = zipfile.ZipFile(path, 'r')
        for name in zh.namelist():
            zh.extract(name, root)
        zh.close()
    
    unzip(sys.argv[1])
    

If a file within the zip has a path of `./usr/bin/script` it will be extracted
to `/usr/bin/script`.

Usage:

    
    
    % python unzip.py myfiles.zip
    

**Update** : To handle tars, use the [tarfile
module](http://docs.python.org/library/tarfile.html). This detects the
compression type using the file extension (gzip, bzip2):

    
    
    import os
    import sys
    import tarfile
    
    def untar(path, root='/'):
        mode = 'r'
        _, ext = os.path.splitext(path)
        if ext in ('.gz', '.bz2'):
            mode += ':' + ext[1:]
        th = tarfile.open(path, mode)
        for info in th.getmembers():
            th.extract(info, root)
        th.close()
    
    untar(sys.argv[1])
    

**Updated** If you can't use the zipfile or tarfile modules, you can invoke
corresponding system commands to get the same results:

    
    
    import os
    import subprocess
    import sys
    
    def untar(path, root):
        subprocess.call(['tar', '-C', root, '-xf', path])
    
    def unzip(path, root):
        subprocess.call(['unzip', os.path.abspath(path)], cwd=root)
    
    path = sys.argv[1]
    dest = os.path.abspath(sys.argv[2])
    if not os.path.exists(dest):
        os.makedirs(dest)
    if path.endswith('.zip'):
        unzip(path, dest)
    else:
        untar(path, dest)
    

