Created
April 27, 2020 11:07
-
-
Save gustavohenrique/6e2f8d72fac59383d7e6e01f28114fdc to your computer and use it in GitHub Desktop.
Create a Windows USB install stick using Linux machine
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/bash | |
# uses (modified) WoeUSB's "listUsb" to get all USB devices | |
# WoeUSB, listUsb: Copyright © 2013 Colin GILLE / congelli501 | |
# WoeUSB, listUsb: Copyright © 2017 slacka et. al. | |
# uses (modified) Janne Korhonen's installer script | |
# https://ypcs.fi/howto/2018/12/01/windowsiso/ | |
# | |
# | |
# Dependencies: apt-get install wimtools parted rsync wimtools | |
declare -a USB_DEVICES=() | |
ISO_FILE=$1 | |
function createUsbInstaller() { | |
DEVICE=$1 | |
DEVICE_DIR="$(echo $DEVICE | cut -d ' ' -f1)" | |
TEMP_DIR="$(mktemp -d winimage-XXXXXX)" | |
MOUNT_TEMP_DIR="$(mktemp -d winmount-XXXXXX)" | |
SOURCE="./$MOUNT_TEMP_DIR/mounted_iso" | |
TARGET="./$MOUNT_TEMP_DIR/mounted_usb" | |
# Directory for mounting the ISO image | |
mkdir "${SOURCE}" | |
# Directory for mounting the USB stick | |
mkdir "${TARGET}" | |
# Create GPT partition table, one FAT32 partition that uses 100% of available space | |
# first create msdos table to ensure that existing table is purged | |
echo "Creating partitions..." | |
parted --script "${DEVICE_DIR}" \ | |
mklabel msdos \ | |
mklabel gpt \ | |
mkpart primary fat32 1 100% \ | |
set 1 msftdata on & | |
wait && sleep 5 | |
# Just to make sure that partition is correctly formatted as FAT32 | |
mkfs.vfat "${DEVICE_DIR}1" | |
# Mount Windows ISO image for file copying | |
mount -oloop "${ISO_FILE}" "${SOURCE}" | |
# Mount USB stick, partition 1 | |
mount "${DEVICE_DIR}1" "${TARGET}" | |
# Copy all files from ISO image to temporary directory | |
rsync -avh --no-o --no-g "${SOURCE}/" "${TEMP_DIR}/" | |
# Split the install.wim file to smaller parts (max 250MB), to temporary directory | |
wimlib-imagex split "${TEMP_DIR}/sources/install.wim" "${TEMP_DIR}/sources/install.swm" 250 | |
# Finally, copy resulting data structure, without large file (install.wim) to the USB stick | |
rsync -avh --no-o --no-g --exclude="install.wim" "${TEMP_DIR}/" "${TARGET}/" | |
# Ensure that everything has been written to disk | |
sync | |
sync | |
# Unmount, your stick is ready now | |
umount "${SOURCE}" | |
umount "${TARGET}" | |
rm -rf "${TEMP_DIR}" | |
rm -rf "${MOUNT_TEMP_DIR}" | |
echo "DONE" | |
exit | |
} | |
set -o errexit | |
set -o errtrace | |
set -o nounset | |
set -o pipefail | |
# Show all devices, not just removable ones | |
declare -i show_all_devices=0 | |
if [ "$#" -ge 1 ] \ | |
&& [ "$1" = 'all' ]; then | |
show_all_devices=1 | |
fi | |
is_removable_and_writable_device(){ | |
local block_device_name="$1" | |
local -r sysfs_block_device_dir="/sys/block/${block_device_name}" | |
# We consider device not removable if the removable sysfs item not exist | |
if [ -f "${sysfs_block_device_dir}/removable" ] \ | |
&& [ "$(cat "${sysfs_block_device_dir}/removable")" -eq 1 ]\ | |
&& [ "$(cat "${sysfs_block_device_dir}/ro")" -eq 0 ]; then | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
declare block_device | |
declare device_capacity | |
declare device_model | |
while read block_device_name; do | |
if grep --extended-regexp "^sr.*$|^cdrom.*$" <<< "${block_device_name}" >/dev/null; then | |
# Known non-target blacklist | |
continue | |
# NOTE: We might not need this check at all as loop devices also has removable sysfs entry | |
# elif grep '^loop.*$' <<< "${block_device_name}" >/dev/null; then | |
# if [ "${show_all_devices}" -eq 0 ]; then | |
# continue | |
# fi | |
elif ! is_removable_and_writable_device "${block_device_name}"; then | |
if [ "${show_all_devices}" -eq 0 ]; then | |
continue | |
fi | |
fi | |
# FIXME: Needs a more reliable detection mechanism instead of simply assuming it is under /dev | |
block_device="/dev/${block_device_name}" | |
device_capacity="$(\ | |
lsblk\ | |
--output SIZE\ | |
--noheadings\ | |
--nodeps\ | |
"${block_device}"\ | |
)" | |
device_model="$(\ | |
lsblk\ | |
--output MODEL\ | |
--noheadings\ | |
--nodeps\ | |
"${block_device}"\ | |
| sed 's/\s//g' | |
)" | |
# It's possible that the device has no model(e.g. loop device) | |
# Push USB device to USB_DEVICES | |
if [ -n "${device_model}" ]; then | |
USB_DEVICES+=( "${block_device} (${device_model}, $device_capacity)" ) | |
else | |
USB_DEVICES+=( "${block_device} ($device_capacity)" ) | |
fi | |
done < <(lsblk --output NAME --noheadings --nodeps) | |
echo "Target device:" | |
select device in "${USB_DEVICES[@]}" "Exit"; do | |
case $device in | |
/dev/*) | |
echo "$device selected" | |
createUsbInstaller $device | |
;; | |
"Exit") | |
break | |
;; | |
*) | |
echo "Invalid option $REPLY" | |
;; | |
esac | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment