Quick file renamer

Wrote this to clean up data from OUT-prefixed image files that I mistakenly saved without an extension on my tablet. I’m keeping my hand in to stay on top of Python for the hell of it. Since I was too lazy to rely on something else to do the job, I figured I could write something faster than a search engine would give me solid results.

I’d guess it took me longer to write comment lines than the code itself.

import os

def rename_out_files_interactive_with_options():
    “””
    Interactively renames files in a user-chosen folder (with common path options)
    that start with ‘OUT’. Shows files with no extensions before adding ‘.jpg’.
    This code is designed to be run in a PyDroid environment.
    “””
    print(“— PyDroid File Renamer —“)

    # Step 1: Allow user to choose the folder with common options
    common_paths = {
        ‘1’: os.path.join(os.path.expanduser(‘~’), ‘Download’),
        ‘2’: ‘/sdcard/Download’,
        ‘3’: ‘/storage/emulated/0/Download’,
        ‘4’: ‘/sdcard/DCIM’ # Common for camera photos
    }

    selected_folder = None
    while selected_folder is None:
        print(“\nChoose a folder to process:”)
        print(”  1) Your common Downloads folder (e.g., /storage/emulated/0/Download)”)
        print(”  2) /sdcard/Download”)
        print(”  3) /storage/emulated/0/Download (Often the same as 1 or 2)”)
        print(”  4) /sdcard/DCIM (For camera photos)”)
        print(”  C) Enter a custom path”)
        print(”  Q) Quit”)

        choice = input(“Enter your choice (1, 2, 3, 4, C, or Q): “).strip().upper()

        if choice == ‘Q’:
            print(“Exiting the script. No files were modified.”)
            return

        if choice in common_paths:
            path_attempt = common_paths[choice]
            if os.path.isdir(path_attempt):
                selected_folder = path_attempt
                print(f”Selected folder: {selected_folder}”)
            else:
                print(f”Warning: The chosen common path ‘{path_attempt}’ does not exist or is not a directory.”)
                print(“Please ensure this path is correct for your device, or try a different option.”)
        elif choice == ‘C’:
            custom_path = input(“Enter the full custom path: “).strip()
            if os.path.isdir(custom_path):
                selected_folder = custom_path
                print(f”Selected folder: {selected_folder}”)
            else:
                print(f”Error: ‘{custom_path}’ is not a valid directory. Please try again.”)
        else:
            print(“Invalid choice. Please enter 1, 2, 3, 4, C, or Q.”)

    target_folder = selected_folder

    print(f”\n— Scanning for ‘OUT’ files in: {target_folder} —“)
    files_to_process = []
    files_with_extensions = []

    try:
        for filename in os.listdir(target_folder):
            if filename.startswith(“OUT”):
                file_path = os.path.join(target_folder, filename)

                if os.path.isfile(file_path):
                    name, ext = os.path.splitext(filename)
                    if not ext:  # No extension
                        files_to_process.append(filename)
                    else:
                        files_with_extensions.append(filename)
                else:
                    print(f”Skipping ‘{filename}’: Is a directory.”)

    except PermissionError:
        print(“\nPermission denied: PyDroid may need storage permissions to access the chosen folder.”)
        print(“Please go to PyDroid settings (or Android app settings) and grant storage permissions.”)
        return
    except FileNotFoundError:
        print(f”\nError: The folder ‘{target_folder}’ was not found. This should not happen if previous checks passed.”)
        print(“Please verify the path and PyDroid’s storage permissions.”)
        return
    except Exception as e:
        print(f”\nAn unexpected error occurred during scanning: {e}”)
        return

    # Step 2: Show files with no extensions before running
    if not files_to_process and not files_with_extensions:
        print(f”\nNo files starting with ‘OUT’ were found in ‘{target_folder}’.”)
        return

    print(“\n— Found files starting with ‘OUT’ —“)
    if files_to_process:
        print(“\nThe following ‘OUT’ files currently have NO extension and will have ‘.jpg’ added:”)
        for filename in files_to_process:
            print(f”- {filename}”)
    else:
        print(“No ‘OUT’ files found without an extension that need ‘.jpg’ added.”)

    if files_with_extensions:
        print(“\nThe following ‘OUT’ files already have an extension and will be skipped:”)
        for filename in files_with_extensions:
            print(f”- {filename}”)
    else:
        print(“No ‘OUT’ files found that already have an extension.”)

    if not files_to_process:
        print(“\nNo files to rename. Exiting.”)
        return

    # Step 3: Confirmation before renaming
    print(“\n— Renaming Confirmation —“)
    confirm = input(“Do you want to proceed with renaming these files? (yes/no): “).lower().strip()

    if confirm == ‘yes’:
        files_renamed_count = 0
        print(“\n— Starting Renaming Process —“)
        for filename in files_to_process:
            original_file_path = os.path.join(target_folder, filename)
            name, _ = os.path.splitext(filename)
            new_name = name + “.jpg”
            new_file_path = os.path.join(target_folder, new_name)
            try:
                os.rename(original_file_path, new_file_path)
                print(f”Renamed: ‘{filename}’ to ‘{new_name}'”)
                files_renamed_count += 1
            except OSError as e:
                print(f”Error renaming ‘{filename}’: {e}”)
            except Exception as e:
                print(f”An unexpected error occurred while renaming ‘{filename}’: {e}”)

        print(f”\nFinished renaming. Total files renamed: {files_renamed_count}”)
    else:
        print(“\nRenaming cancelled by user. No files were modified.”)

# Call the function to run the interactive renaming process
if __name__ == “__main__”:
    rename_out_files_interactive_with_options()

Leave a Reply