Created
June 5, 2026 17:12
-
-
Save bodja/95f00a1d79e0fa1480e734a9b5726c8b to your computer and use it in GitHub Desktop.
Windows iso to USB
This file contains hidden or 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 bash | |
| set -euo pipefail | |
| # Usage: | |
| # ./makewin11.sh list external disks, then exit | |
| # ./makewin11.sh <disk> <iso> build the USB | |
| # <disk> e.g. /dev/disk4 (see the list above) | |
| # <iso> path to the Windows 11 ISO | |
| list_disks() { | |
| echo "External / removable disks:" | |
| echo | |
| # Show only external, physical disks with their size and identifier | |
| diskutil list external physical 2>/dev/null || diskutil list | |
| echo | |
| echo "Pick the whole-disk identifier (e.g. /dev/disk4) that matches your USB by SIZE." | |
| echo "Then run: $0 /dev/diskN /path/to/Win11.iso" | |
| } | |
| # No args (or explicit list flag): show disks and exit | |
| if [ "$#" -eq 0 ] || [ "${1:-}" = "list" ] || [ "${1:-}" = "-l" ]; then | |
| list_disks | |
| exit 0 | |
| fi | |
| if [ "$#" -ne 2 ]; then | |
| echo "Usage: $0 <disk> <iso> (run with no args to list disks)" >&2 | |
| exit 1 | |
| fi | |
| DISK="$1" | |
| ISO="$2" | |
| # Validate the disk: must exist AND be external (guards against wiping an internal drive) | |
| if [ ! -e "$DISK" ]; then | |
| echo "Error: disk '$DISK' not found. Run '$0' with no args to list disks." >&2 | |
| exit 1 | |
| fi | |
| if ! diskutil info "$DISK" 2>/dev/null | grep -qiE 'Device Location: *External|Internal: *No'; then | |
| echo "Error: '$DISK' does not look like an external disk. Refusing to continue." >&2 | |
| echo "Run '$0' with no args to see external disks." >&2 | |
| exit 1 | |
| fi | |
| if [ ! -f "$ISO" ]; then | |
| echo "Error: ISO '$ISO' not found." >&2 | |
| exit 1 | |
| fi | |
| # Final confirmation before destroying data | |
| echo "About to ERASE this disk:" | |
| diskutil info "$DISK" | grep -iE 'Device Identifier|Media Name|Disk Size' | |
| echo | |
| read -r -p "Type ERASE to continue: " confirm | |
| [ "$confirm" = "ERASE" ] || { echo "Aborted."; exit 1; } | |
| TMP="$HOME/wim_temp" | |
| USB="/Volumes/WINUSB" | |
| # 1. Wipe + format FAT32 / MBR | |
| diskutil unmountDisk force "$DISK" 2>/dev/null || true | |
| diskutil eraseDisk MS-DOS "WINUSB" MBR "$DISK" | |
| # 2. Mount ISO, capture mount point | |
| MNT=$(hdiutil attach "$ISO" -nobrowse | grep -o '/Volumes/.*' | head -1) | |
| echo "ISO mounted at: $MNT" | |
| # 3. Copy everything except oversized install.wim | |
| rsync -avh --progress --exclude=sources/install.wim "$MNT/" "$USB/" | |
| # 4. Split install.wim on internal SSD first | |
| rm -rf "$TMP"; mkdir -p "$TMP" | |
| wimlib-imagex split "$MNT/sources/install.wim" "$TMP/install.swm" 3800 | |
| # 5. Copy split pieces onto the stick | |
| rsync -avh --progress "$TMP"/install*.swm "$USB/sources/" | |
| # 6. Verify: no file over 4GB (should print nothing) | |
| echo "-- files over 4GB (should be empty): --" | |
| find "$USB" \( -name .Spotlight-V100 -o -name .fseventsd \) -prune -o -type f -size +4000000k -print 2>/dev/null | |
| # 7. Verify boot file present | |
| ls -la "$USB/efi/boot/bootx64.efi" | |
| # 8. Cleanup + eject | |
| hdiutil detach "$MNT" | |
| rm -rf "$TMP" | |
| diskutil eject "$DISK" | |
| echo "Done." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment