Last active
June 26, 2023 19:39
-
-
Save einsteinx2/ccdd6522ec08cc74f2e16beb0e95f7c6 to your computer and use it in GitHub Desktop.
Small python script to convert a folder full of *.nkit.iso files into the folder structure needed for use on a modded Wii
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Requires: Python 3.7 (might work on 3.6, but I haven't tested) | |
# Purpose: Convert a folder full of *.nkit.iso (uncompressed) files into the folder structure needed for use on a modded Wii | |
# File names: Games must be named like "Game Name [GAMEID].nkit.iso" | |
# Multi-disc: Multi-disc games must be named like "Game Name (Disc 1) [GAMEID].nkit.iso" and "Game Name (Disc 2) [GAMEID].nkit.iso" | |
# Notes: Supports both copy and move, if you name your games differently you'll need to modify the script as it was made for my personal use | |
# TODO: | |
# - Better documentation | |
# - Support different naming schemes | |
# - Support Python 2.7 (maybe) | |
import os | |
import glob | |
import collections | |
import array | |
import shutil | |
import argparse | |
from pprint import pprint | |
from pathlib import Path | |
from operator import attrgetter | |
# Constants | |
NKIT_EXT = '.nkit.iso' | |
DISC1_STR = ' (Disc 1) ' | |
DISC2_STR = ' (Disc 2) ' | |
DISC1_FILENAME = 'game.iso' | |
DISC2_FILENAME = 'disc2.iso' | |
# Named tuple representing each disc | |
DiscImage = collections.namedtuple('DiscImage', 'in_path, in_filename, out_foldername, out_filename') | |
# Find all nkit isos and in the input path and calculate their output folder and file names | |
def process_discs(in_path): | |
# Array of processed discs so we can do all the processing first before modifying the filesystem | |
discs = [] | |
# Process the list of discs | |
glob_str = os.path.join(in_path, F'*{NKIT_EXT}') | |
for in_path in glob.iglob(glob_str): | |
# Get the original nkit iso file name | |
in_filename = os.path.basename(in_path) | |
# Get the file name without the extension to use as the folder name | |
out_foldername = in_filename[:-len(NKIT_EXT)] | |
# Check if it's a multi-disc game and handle it properly | |
out_filename = DISC1_FILENAME | |
if DISC1_STR in in_filename: | |
# Build the correct folder name by removing the (Disc 1) string | |
split = out_foldername.split(DISC1_STR) | |
assert len(split) == 2, F"Could not split game disc 1 name, len(split) = {len(split)}" | |
out_foldername = F"{split[0]} {split[1]}" | |
elif DISC2_STR in in_filename: | |
# Build the correct folder name by removing the (Disc 2) string | |
split = out_foldername.split(DISC2_STR) | |
assert len(split) == 2, F"Could not split game disc 2 name, len(split) = {len(split)}" | |
out_foldername = F"{split[0]} {split[1]}" | |
# Second discs must be named disc2.iso | |
out_filename = DISC2_FILENAME | |
# Create the DiscImage named tuple and add it to the list of discs | |
discs.append(DiscImage(in_path = in_path, in_filename = in_filename, out_foldername = out_foldername, out_filename = out_filename)) | |
# Sort by file name | |
discs.sort(key = attrgetter('in_filename')) | |
# Return the list of DiscImage named tuples | |
return discs | |
# Copy (or move) the files to their new locations | |
def copy_discs(discs, out_path, move = False, dry_run = False): | |
for disc in discs: | |
# Determine the output path | |
out_folder_path = os.path.join(out_path, disc.out_foldername) | |
out_file_path = os.path.join(out_folder_path, disc.out_filename) | |
# Create the output directory | |
Path(out_folder_path).mkdir(parents = True, exist_ok = True) | |
if move is True: | |
# Move the file | |
print(F'Moving "{disc.in_path}" to "{out_file_path}".....', end = '') | |
if dry_run is False: | |
shutil.move(disc.in_path, out_file_path) | |
print("Done!") | |
else: | |
# Copy the file | |
print(F'Copying "{disc.in_path}" to "{out_file_path}".....', end = '') | |
if dry_run is False: | |
shutil.copy2(disc.in_path, out_file_path) | |
print("Done") | |
def parse_args(): | |
parser = argparse.ArgumentParser() | |
# Positional arguments | |
parser.add_argument('in_path', help = 'Path to the input directory that contains *.nkit.iso files that are in the format "Name Of Game [GAMEID].nkit.iso"') | |
parser.add_argument('out_path', help = 'Path to the output directory where the Wii / Nintendont file structure will be created (e.g. your "games" folder)') | |
# Optional arguments | |
parser.add_argument('-m', '--move', help='Move the disc images instead of copying them (WARNING! Make sure you have a backup copy first!)', action='store_true') | |
parser.add_argument('-d', '--dry-run', help='Just print out what would happen, but do not copy or move any files', action='store_true') | |
return parser.parse_args() | |
def main(): | |
args = parse_args() | |
if args.dry_run is True: | |
print("Performing dry run...\n") | |
discs = process_discs(args.in_path) | |
copy_discs(discs, args.out_path, args.move, args.dry_run) | |
# Execute only if run as a script | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment