-
Notifications
You must be signed in to change notification settings - Fork 1
/
bootable-usb-win10.sh
executable file
·201 lines (180 loc) · 5.31 KB
/
bootable-usb-win10.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/bin/bash
set -e
# Properties
vers='v0.7'
versDate='2020-05-17'
# Statics
red=$'\e[1;31m'
grn=$'\e[1;32m'
yel=$'\e[1;33m'
blu=$'\e[1;34m'
mag=$'\e[1;35m'
cyn=$'\e[1;36m'
end=$'\e[0m'
quesMsg="${yel}%s [if not '%s']:${end} "
quesEMsg="${yel}%s [if not '%s' (%s)]:${end} "
erroMsg="${red}✘\t%s [expected: '%s']${end}\n"
erroEMsg="${red}✘\t%s [expected: '%s' (%s)]${end}\n"
warnMsg="\n${mag}!\t%s${end}\n\n"
taskMsg="${yel}%s:${end}\t"
rsltMsg="${grn}✔${end}\n"
nwLnMsg='\n\n---\n\n\n'
# Functions
function get_input {
if ! [[ -z "${3}" ]]
then
local msg=$(printf -- "${quesEMsg}" "${1}" "${2}" "${3}")
else
local msg=$(printf -- "${quesMsg}" "${1}" "${2}")
fi
read -p "${msg}"
REPLY=$(printf -- '%s' "${REPLY}" | tail -n 1 | sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*$//g')
if ! [[ -z "${REPLY}" ]]
then
printf -- '%s' "${REPLY}"
else
printf -- '%s' "${2}"
fi
}
function raise_error {
if ! [[ -z "${3}" ]]
then
local msg=$(printf -- "${erroEMsg}" "${1}" "${2}" "${3}")
else
local msg=$(printf -- "${erroMsg}" "${1}" "${2}")
fi
printf -- '%s\n' "${msg}" 1>&2
if ! [[ -z "${4}" ]]
then
printf -- '%s\n' "${4}" 1>&2
fi
exit 1
}
function raise_sig_error {
printf -- '\n'
raise_error "${1}" "${2}" "${3}"
}
while getopts 'av' flag 2> /dev/null
do
case "${flag}" in
a) printf -- '%s\n' 'Author: ionysos (https://ionysos.github.io/)'
exit 0;;
v) printf -- '%s\n%s\n%s\n' "Version: ${vers} (${versDate})" \
"$(basename -- $0) (https://github.com/ionysos/macOS-tools/blob/master/bootable-usb-win10.sh)" \
'License: MIT (https://github.com/ionysos/macOS-tools/blob/master/LICENSE)'
exit 0;;
*) raise_error 'Flag not supported' "-a', '-v";;
esac
done
trap "raise_sig_error 'Unknown error' 'NONE'" SIGHUP
trap "raise_sig_error 'User abortion' 'NONE'" SIGINT SIGTERM
## Check OS
if [[ "${OSTYPE}" != 'darwin'* ]]
then
raise_error 'OS not supported' 'macOS' 'darwin'
fi
## Prepare system
if ! [[ -x "$(command -v wimlib-imagex)" ]]
then
raise_error 'Dependency not available' 'wimlib' 'wimlib-imagex' "$(printf -- '\t%s\n\t\t%s' 'E.g.: install it via Homebrew (https://brew.sh/)' 'brew install wimlib')"
fi
## Variables
win10ISO=$(mdfind 'win 10 .iso' | head -n 1)
usbDrive=$(diskutil list | sed -n 's|^/dev/\(disk[0-9]*\).*|\1|p' | tail -n 1)
usbDriveName=$(df | sed -n "s|^/dev/${usbDrive}s[0-9]*\(.*\).*|\1|p" | tail -n 1 | sed -n 's|.*/\(.*\)$|\1|p')
## Print download URL
printf -- '%s\n\n' 'Download Win10 ISO file from: https://www.microsoft.com/software-download/windows10'
## Ask for file path
win10ISO=$(get_input 'Win10 ISO file path' "${win10ISO}")
## Ask for disk name
usbDrive=$(get_input 'USB drive disk name' "${usbDrive}" "${usbDriveName}")
## Print formatting warning
printf -- "${warnMsg}" 'Disk formatting leads to irrecoverable data erasure'
## Ask for disk formatting
eraseDisk='no'
eraseDisk=$(get_input "Format disk '${usbDrive}'? ('yes')" "${eraseDisk}")
## Format disk
if [[ "${eraseDisk}" == 'yes' ]]
then
if [[ -e "/dev/${usbDrive}" ]]
then
usbName='WIN10'
printf -- "\n${taskMsg}\t\t\t\t\t\t" "Format disk '${usbDrive}'"
diskutil eraseDisk MS-DOS "${usbName}" MBR "${usbDrive}" > /dev/null
sleep 3
printf -- "${rsltMsg}"
else
raise_error 'Disk not available' "${usbDrive}"
fi
else
raise_error 'User abortion' 'NONE'
fi
## Mount ISO
if [[ -f "${win10ISO}" ]]
then
printf -- "${taskMsg}\t" "Mount ISO '${win10ISO}'"
volume=$(hdiutil mount "${win10ISO}" | cut -f3)
sleep 3
printf -- "${rsltMsg}"
else
raise_error 'ISO not available' "${win10ISO}"
fi
## Print long-lasting copy warning
printf -- "${warnMsg}" 'File copy lasts several minutes (~10min)'
## Copy files
usbVolume="/Volumes/${usbName}"
if [[ -d "${volume}" ]] && [[ -d "${usbVolume}" ]]
then
maxMBSize='4000'
printf -- "${taskMsg}" "Copy files ('${volume}' -> '${usbVolume}')"
printf -- '%s' '...'
rsync -qa --max-size="${maxMBSize}M" -- "${volume}/" "${usbVolume}"
specFiles=($(find "${volume}" -type f -size "+${maxMBSize}M" 2> /dev/null))
if [[ ${#specFiles[@]} == 0 ]]
then
printf -- '%s' '1/1...'
else
printf -- '%s' '1/2...'
specFileEnd='.wim'
specFileSEnd='.swm'
for currSpecFile in ${specFiles[@]}
do
if [[ -f "${currSpecFile}" ]]
then
currSpecFileEnd=$(printf '%s' "${currSpecFile}" | tail -n 1 | sed -n 's|.*\(\..*\)$|\1|p')
if [[ "${currSpecFileEnd}" == "${specFileEnd}" ]]
then
currSpecFileName=$(printf '%s' "${currSpecFile}" | tail -n 1 | sed -n "s|${volume}/\(.*\)${specFileEnd}$|\1|p")
wimlib-imagex split -- "${currSpecFile}" "${usbVolume}/${currSpecFileName}${specFileSEnd}" "${maxMBSize}" > /dev/null
else
raise_error 'Win10 file extension not supported' "${specFileEnd}" "at ${currSpecFile}"
fi
else
raise_error 'Win10 file not available' "${currSpecFile}"
fi
done
printf -- '%s' '2/2...'
fi
sleep 3
printf -- " ${rsltMsg}"
else
raise_error 'Volume(s) not available' "${volume}', '${usbVolume}"
fi
## Eject disk
if [[ -d "${usbVolume}" ]]
then
printf -- "${taskMsg}\t\t\t\t\t" "Eject disk '${usbVolume}'"
hdiutil eject "${usbVolume}" > /dev/null
printf -- "${rsltMsg}"
else
raise_error 'Disk not available' "${usbVolume}"
fi
## Eject volume
if [[ -d "${volume}" ]]
then
printf -- "${taskMsg}\t\t" "Eject volume '${volume}'"
hdiutil eject "${volume}" > /dev/null
printf -- "${rsltMsg}"
else
raise_error 'Volume not available' "${volume}"
fi