diff --git a/iso2usb-mac.py b/iso2usb-mac.py new file mode 100644 index 0000000..7df8106 --- /dev/null +++ b/iso2usb-mac.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +# Description: An easy CLI interface for writing ISOs to USB sticks on macOS. +# Usage: python3 iso2usb-mac.py +# Author: Justin Oros +# Source: https://github.com/JustinOros +# Dependencies: dd, diskutil (standard utils on macOS) + +import os +import subprocess +import sys + +def list_files(extension): + # List files in the current directory with the ISO extension. + return [f for f in os.listdir() if f.endswith(extension)] + +def list_external_disks(): + # List external disks (USB drives) currently mounted on macOS. + result = subprocess.run(['diskutil', 'list'], capture_output=True, text=True) + disks = [] + for line in result.stdout.splitlines(): + if "/dev/disk" in line and "external" in line: + parts = line.split() + disks.append(parts[0]) + return disks + +def prompt_choice(options, prompt): + # Prompt user to select an option from a list. + while True: + for idx, option in enumerate(options, 1): + print(f"{idx}. {option}") + try: + choice = int(input(f"{prompt} (Enter the number): ")) + if 1 <= choice <= len(options): + return options[choice - 1] + else: + print(f"Please enter a number between 1 and {len(options)}.") + except ValueError: + print("Invalid input. Please enter a number.") + +def prompt_speed_choice(): + # Prompt the user to select the write speed. + print("\nSelect the write speed:") + print("1) Slow (1M)") + print("2) Regular (4M) [default]") + print("3) Fast (8M)") + + while True: + choice = input("Enter the number (or press RETURN for default): ").strip() + + if choice == "": + return "4M" # Default to regular speed (4M) + elif choice == "1": + return "1M" # Slow speed + elif choice == "2": + return "4M" # Regular speed + elif choice == "3": + return "8M" # Fast speed + else: + print("Invalid input. Please enter 1, 2, or 3, or press RETURN for default.") + +def confirm(prompt): + # Prompt user to confirm an action. + while True: + confirm = input(f"{prompt} (y/n): ").strip().lower() + if confirm in ['y', 'n']: + return confirm == 'y' + print("Please enter 'y' or 'n'.") + +def main(): + # List ISOs in the current directory + iso_files = list_files('.iso') + if not iso_files: + print("No ISO files found in the current directory.") + sys.exit(1) + + # List available external disks + disks = list_external_disks() + if not disks: + print("No external disks found.") + sys.exit(1) + + # Prompt user to select ISO + selected_iso = prompt_choice(iso_files, "Select an ISO file") + + # Prompt user to select disk + selected_disk = prompt_choice(disks, "Select a disk") + + # Prompt user to select write speed + selected_speed = prompt_speed_choice() + + # Overview of selected ISO, disk, and write speed + print(f"\nYou selected:") + print(f"ISO: {selected_iso}") + print(f"Disk: {selected_disk}") + print(f"Write speed: {selected_speed}") + + # Confirm before proceeding + if confirm("Are you sure you want to proceed? This will overwrite the disk"): + print("Writing ISO to disk...") + + # Execute dd command to write the ISO to the selected disk with the selected block size + try: + # WARNING: dd command will overwrite the disk, be sure! + subprocess.run(['sudo', 'dd', f'if={selected_iso}', f'of={selected_disk}', 'bs=' + selected_speed, 'status=progress', 'oflag=sync'], check=True) + + # After writing the ISO, eject the disk to make it ready for use + subprocess.run(['sudo', 'diskutil', 'eject', selected_disk], check=True) + + print("ISO successfully written to disk.") + except subprocess.CalledProcessError as e: + print(f"Error while writing to disk: {e}") + else: + print("Operation cancelled.") + +if __name__ == "__main__": + main()