soledad penadés
repeat 4[fd 100 rt 90]

Create .ZIPs from multiple folders

There we go with yet another exercise in Python :-)

The idea here is to archive several folders, having each folder in a ZIP file. So if you have two folders, A and B, you end up with A.zip and B.zip.

No doubt this can be done with shell programming (and it will be much better since this solution doesn't provide support for recursion) but this is intended as a way of improving my python skills, so no moaning about the choice of language here! ;-)

And here is the little script:

import os
import sys
import zipfile

if len(sys.argv) > 1:
        folder = sys.argv[1]
else:
        folder = '.'
       
for item in os.listdir(folder):
       
        full_path = os.path.join(folder, item)
       
        if not os.path.isdir(full_path):
                continue
       
        dst_filename = item + '.zip'
       
        dst_item = os.path.join(folder, dst_filename)
       
       
        if os.path.exists(dst_item) and os.path.getsize(dst_item) > 0:
                continue
       
        output_file = zipfile.ZipFile(dst_item, "w", zipfile.ZIP_DEFLATED)
       
        for item_file in os.listdir(full_path):
                output_file.write(os.path.join(full_path, item_file), item_file)
               
        output_file.close()

You can download it from my supersnippets repository, and then execute it with

python zip_folders.py name_of_folder_to_process

Maybe changing the way I do the imports would help, so instead of doing import os and then using os.listdir, I would write from os import listdir and then simply use listdir from then on, but for some reason I kind of prefer the more verbose way for now, so that I don't have to guess where does each function come from.

I suppose once I get more fluent with Python, I won't need to use those long statements.

// 3 responses to Create .ZIPs from multiple folders

Sergi Mansilla
Sergi Mansilla
20080827

Good work and good blog!

Your script seems likely to throw an error in the following lines:

for item_file in os.listdir(full_path):
                output_file.write(os.path.join(full_path, item_file), item_file)

given that you are handling files and folders at the same time, and as far as I can remember (not sure though), it will attempt to read the folder information as if it were a file to write its contents inside the .zip file. I think you should filter the folders out as you did already some lines before.

Here is my attempt at writing a recursive solution for the problem:

from os import listdir, walk, path
from os.path import join, isdir, exists
import sys
import zipfile

if len(sys.argv) > 1:
        folder = sys.argv[1]
else:
        folder = '.'

def dirwalk(dir):
    for root, dirs, files in walk(dir):
        for name in dirs:
            yield [root, name]

for ff, item in dirwalk(folder):
    folder_path = join(ff, item)

    dst_item = folder_path + '.zip'

    if not exists(dst_item):
        output_file = zipfile.ZipFile(dst_item, "w", zipfile.ZIP_DEFLATED)
        file_path = join(folder_path,file)
        for item_file in [file for file in listdir(folder_path) if not isdir(file_path)]:
            output_file.write(file_path, item_file)
        output_file.close()

Sergi Mansilla
Sergi Mansilla
20080827

Ugh it didn't indent my code :(

sole
sole
20080827

Hey! Thanks for the improved script. You're right, it didn't look for anything recursive, because for this specific case I hadn't folders inside folders, only plain files.

By the way, I applied some formatting to your code :)

I didn't know about yield in Python, and I'm glad to see how my supposition about imports was right. I think I'm in the right way :D

Thanks again for all!

Feel free to leave a reply

Comments are moderated: Rude and offtopic ones are out!