Rename files in subdirectories with the root directory name in an zipfile

Question:

I have the following directory structure within my zip file:

myzip.zip
    - directory 1
        - subdirectory 1
            - imageA.jpg
            - imageB.jpg
    - directory 2 
        - subdirectory 2
            - imageA.jpg
            - imageB.jpg

And my goal is to rename the .jpg files to main directory name like so:

myzip.zip
    - directory 1
        - subdirectory 1
            - directory 1-1.jpg
            - directory 1-2.jpg
    - directory 2 
        - subdirectory 2
            - directory 2-1.jpg
            - directory 2-2.jpg

Thereby taking in account that an subdirectory can contain multiple .jpg files adding an incremental number after each newly renamed .jpg file starting from 1 (hence the new filename directory 1-1.jpg).

And lastly I would like to write these changes to an new zipfile, keeping the same structure with the only difference the changed names from the .jpg files.

My idea in code:

import zipfile

source = zipfile.ZipFile("myzip.zip", 'r')
target = zipfile.ZipFile(source.filename+"_renamed"+".zip", 'w', zipfile.ZIP_DEFLATED)

for file in source.infolist():
    filename = file.filename #directory 1/subdirectory 1/imageA.jpg
    rootname, image_name = filename.split("/subdirectory")
    # rootname results in: directory 1 
    # image_name results in /subdirectory/image_name.jpg
    new_image = image_name.replace(image_name, "/subdirectory/"+rootname+image_name[4:])
    target.write(rootname+new_image)

I though (haven’t really tested it) about using zipfile.Zipfile and something of using the above code, but to be honest I have not really an idea how to solve this.

Any ideas or examples?

Asked By: Tobias S

||

Answers:

Here’s some pseudocode representing how you could implement this:

unzip myzip.zip
for directory in unzipped:
    for subdirectory in directory:
        i = 0
        for file in subdirectory:
            file.rename(f"{directory.name}-{i}.jpg")
            i += 1
zip unzipped
Answered By: bobtho'-'

Based on @bobtho’-‘ pseudocode I’ve created the following program:

import os
import zipfile
import sys
import shutil

root = os.path.join(sys.path[0])
unzipped = os.path.join(root,"unzipped") #a folder to extract/unzip your content to

if not os.path.exists(unzipped):
    print("Create new unzipped directory")
    os.makedirs(unzipped)
elif len(os.listdir(unzipped)) != 0:
    shutil.rmtree(unzipped) # remove the old folder and its contents
    os.makedirs(unzipped)

filename = "myfile.zip"
source = os.path.join(root, filename)

with zipfile.ZipFile(source) as source:
    source.extractall(unzipped)

target = zipfile.ZipFile(source.filename, 'w')

with target:
    for filename in os.listdir(unzipped):
        directory = os.path.join(unzipped, filename)
        for sub_dir in os.listdir(directory): 
            files = os.path.join(unzipped, directory, sub_dir)
            i = 0
            for file in os.listdir(files):
                old_file_path = os.path.join(unzipped, directory, sub_dir, file)
                print(filename)

                renamed_file = "{directory}-{i}.jpg".format(directory=filename, i=i)

                new_file_path = os.path.join(unzipped, directory, sub_dir, renamed_file)
                os.rename(old_file_path, new_file_path)

                directory_to_zip = os.path.relpath(os.path.join(filename, sub_dir, renamed_file))
                target.write(new_file_path, directory_to_zip)
                i += 1
    target.close()

shutil.rmtree(unzipped)

I think its not the best (or fastest) solution, but fitted my goals. Hopefully someone is helped by this.

Answered By: Tobias S