Python: Unlocking ZIPs

Overview

The script defines two main functions: unzip_with_passwords and unzip_and_rename. It attempts to unzip files in a specified directory using a list of passwords and then renames the extracted CSV files according to the ZIP file’s name or names them uniquely if there’s more than one CSV file. The script ensures the creation of necessary directories and cleans up after extraction.

Explanation with Inline Comments

from pathlib import Path
import zipfile

# Directories for ZIP files and extraction output
zip_files_directory = 'files'
output_directory = 'extract'
# List of passwords to try for extracting ZIP files
passwords = [b'0000', b'000', b'00000']

# Ensure the output directory exists
Path(output_directory).mkdir(parents=True, exist_ok=True)

def unzip_with_passwords(zip_file_path, output_dir, passwords):
    extracted = False
    with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
        for password in passwords:
            try:
                # Attempt to extract with the current password
                zip_ref.extractall(output_dir, pwd=password)
                extracted = True
                break  # Successful extraction, exit loop
            except RuntimeError:
                # Incorrect password, try the next one
                continue
    return extracted  # True if extraction succeeded, False otherwise

def unzip_and_rename(zip_file_path, output_dir, passwords):
    # Create a temporary directory based on the ZIP file name
    temp_output_dir = Path(output_dir) / zip_file_path.stem
    temp_output_dir.mkdir(parents=True, exist_ok=True)

    # Try to extract the ZIP file with the given passwords
    if unzip_with_passwords(zip_file_path, temp_output_dir, passwords):
        csv_files = list(temp_output_dir.glob('*.csv'))
        for index, csv_file in enumerate(csv_files, start=1):
            # Determine the new file name
            if len(csv_files) == 1:
                new_name = f"{zip_file_path.stem}.csv"
            else:
                new_name = f"{zip_file_path.stem}-{index}.csv"
            # Rename and move the CSV file
            new_file_path = Path(output_dir) / new_name
            csv_file.rename(new_file_path)
    else:
        # Extraction failed
        print(f"Could not decrypt {zip_file_path.name}")

    # Cleanup: Remove temporary files and directory
    for file in temp_output_dir.iterdir():
        file.unlink()
    temp_output_dir.rmdir()

# Process each ZIP file in the specified directory
for zip_file in Path(zip_files_directory).glob('*.zip'):
    unzip_and_rename(zip_file, Path(output_directory), passwords)

Extracting ZIP Files with Passwords

We start by defining the directories for ZIP files and extraction output, as well as a list of passwords to try to extract ZIP files.

from pathlib import Path
import zipfile

zip_files_directory = 'files'
output_directory = 'extract'
passwords = [b'0000', b'000', b'00000']

Next, we define a function unzip_with_passwords to attempt extraction of a ZIP file with the provided passwords.

def unzip_with_passwords(zip_file_path, output_dir, passwords):
    extracted = False
    with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
        for password in passwords:
            try:
                zip_ref.extractall(output_dir, pwd=password)
                extracted = True
                break
            except RuntimeError:
                continue
    return extracted

Renaming Extracted Files

We then define a function unzip_and_rename to extract the ZIP file and rename the extracted CSV files based on the archive’s name.

def unzip_and_rename(zip_file_path, output_dir, passwords):
    temp_output_dir = Path(output_dir) / zip_file_path.stem
    temp_output_dir.mkdir(parents=True, exist_ok=True)

    if unzip_with_passwords(zip_file_path, temp_output_dir, passwords):
        csv_files = list(temp_output_dir.glob('*.csv'))
        for index, csv_file in enumerate(csv_files, start=1):
            if len(csv_files) == 1:
                new_name = f"{zip_file_path.stem}.csv"
            else:
                new_name = f"{zip_file_path.stem}-{index}.csv"
            new_file_path = Path(output_dir) / new_name
            csv_file.rename(new_file_path)
    else:
        print(f"Could not decrypt {zip_file_path.name}")

    for file in temp_output_dir.iterdir():
        file.unlink()
    temp_output_dir.rmdir()

Processing ZIP Files

Finally, we iterate through each ZIP file in the specified directory, extract its contents, and handle them accordingly.

for zip_file in Path(zip_files_directory).glob('*.zip'):
    unzip_and_rename(zip_file, Path(output_directory), passwords)