windows: 优化 iso 查找

This commit is contained in:
bin456789
2026-08-04 21:10:05 +08:00
parent b941221ec1
commit 27dd00c078
3 changed files with 220 additions and 110 deletions
+4 -3
View File
@@ -356,8 +356,8 @@ bash reinstall.sh netboot.xyz
#### Method 1: Let the Script Automatically Search for ISO #### Method 1: Let the Script Automatically Search for ISO
- The script will search for ISOs from <https://massgrave.dev/genuine-installation-media>, a site that collects official ISOs. - The script will search for ISOs from <https://massgrave.dev/genuine-installation-media> and <https://ntriver.org/download-windows-office>, sites that collect official ISOs.
- Only supports ISOs searching for Windows 10, 11, Server 2019, 2022, 2025. - Only supports ISOs searching for Windows 8.x, 10, 11, Server 2019, 2022, 2025.
```bash ```bash
bash reinstall.sh windows \ bash reinstall.sh windows \
@@ -436,7 +436,8 @@ bash reinstall.sh windows \
- General - General
- <https://msdl.gravesoft.dev> - <https://msdl.gravesoft.dev>
- <https://massgrave.dev/genuine-installation-media> - <https://massgrave.dev/genuine-installation-media> (Recommended, ISOs are up to date)
- <https://ntriver.org/download-windows-office> (Recommended, ISOs are up to date)
- <https://next.itellyou.cn> - <https://next.itellyou.cn>
- <https://www.xitongku.com> - <https://www.xitongku.com>
- <https://www.microsoft.com/software-download/windows10> (Need to open it with a non-Windows User-Agent) - <https://www.microsoft.com/software-download/windows10> (Need to open it with a non-Windows User-Agent)
+4 -3
View File
@@ -356,8 +356,8 @@ bash reinstall.sh netboot.xyz
#### 方法 1: 让脚本自动查找 ISO #### 方法 1: 让脚本自动查找 ISO
- 脚本会从 <https://massgrave.dev/genuine-installation-media> 查找 ISO,该网站专门提供官方 ISO 下载 - 脚本会从 <https://massgrave.dev/genuine-installation-media> 和 <https://ntriver.org/download-windows-office> 查找 ISO,网站专门提供官方 ISO 下载
- 只支持查找 Windows 10, 11, Server 2019, 2022, 2025 的 ISO - 只支持查找 Windows 8.x, 10, 11, Server 2019, 2022, 2025 的 ISO
```bash ```bash
bash reinstall.sh windows \ bash reinstall.sh windows \
@@ -436,7 +436,8 @@ bash reinstall.sh windows \
- 正式版 - 正式版
- <https://msdl.gravesoft.dev> - <https://msdl.gravesoft.dev>
- <https://massgrave.dev/genuine-installation-media> - <https://massgrave.dev/genuine-installation-media> (推荐,ISO 是最新版)
- <https://ntriver.org/download-windows-office> (推荐,ISO 是最新版)
- <https://next.itellyou.cn> - <https://next.itellyou.cn>
- <https://www.xitongku.com> - <https://www.xitongku.com>
- <https://www.microsoft.com/software-download/windows10> (需用非 Windows User-Agent 打开) - <https://www.microsoft.com/software-download/windows10> (需用非 Windows User-Agent 打开)
+212 -104
View File
@@ -874,7 +874,9 @@ is_have_arm_version() {
'enterprise ltsc 2021' | 'iot enterprise ltsc 2021') return ;; 'enterprise ltsc 2021' | 'iot enterprise ltsc 2021') return ;;
esac esac
;; ;;
11) return ;; 11)
return
;;
esac esac
return 1 return 1
} }
@@ -893,9 +895,13 @@ find_windows_iso() {
full_lang=$(english) full_lang=$(english)
case "$basearch" in case "$basearch" in
x86) # 备用,查找功能目前不支持 32 位
arch_win=x86
arch_win_vlsc='32-?bit'
;;
x86_64) x86_64)
arch_win=x64 arch_win=x64
arch_win_vlsc=64bit arch_win_vlsc='64-?bit'
;; ;;
aarch64) aarch64)
arch_win=arm64 arch_win=arm64
@@ -908,82 +914,125 @@ find_windows_iso() {
get_windows_iso_link() { get_windows_iso_link() {
get_label_msdn() { get_label_msdn() {
if [ -n "$server" ]; then case "$version" in
case "$version" in 8 | 8.1)
2019 | 2022 | 2025) case "$edition" in
case "$edition" in '') # windows 8.x core
serverstandard | serverstandardcore) echo _ ;; echo _
serverdatacenter | serverdatacentercore) echo _ ;; ;;
esac pro | enterprise)
echo "$edition"
;; ;;
esac esac
else ;;
case "$version" in 10)
10) case "$edition" in
case "$edition" in home | 'home single language')
home | 'home single language') echo consumer ;; echo 'consumer editions'
pro | enterprise) echo business ;; ;;
education | 'pro education' | 'pro for workstations') pro | enterprise)
case "$arch_win" in echo 'business editions'
arm64) echo consumer ;; ;;
x64) echo business ;; # iso 更小 education | 'pro education' | 'pro for workstations')
esac case "$arch_win" in
;; arm64) echo 'consumer editions' ;; # 只能从 consumer 获取
# iot x86 | x64) echo 'business editions' ;; # iso 更小
'iot enterprise') echo 'iot enterprise' ;;
# iot ltsc
'iot enterprise ltsc 2021') echo "$edition" ;;
# ltsc
'enterprise ltsc 2021')
# arm64 的 enterprise ltsc 2021 要下载 iot enterprise ltsc 2021 iso
case "$arch_win" in
arm64) echo 'iot enterprise ltsc 2021' ;;
x86 | x64) echo 'enterprise ltsc 2021' ;;
esac
;;
esac esac
;; ;;
11) # iot
'iot enterprise')
echo 'iot enterprise'
;;
# ltsc
'enterprise 2015 ltsb' | 'enterprise 2016 ltsb' | 'enterprise ltsc 2019' | 'enterprise ltsc 2021')
case "$arch_win" in
arm64) echo "iot $edition" ;; # 只能从 iot ltsc iso 获取
x86 | x64) echo "$edition" ;;
esac
;;
# iot ltsc
'iot enterprise 2015 ltsb' | 'iot enterprise 2016 ltsb' | 'iot enterprise ltsc 2019' | 'iot enterprise ltsc 2021')
echo "$edition"
;;
esac
;;
11)
case "$edition" in
home | 'home single language')
echo 'consumer editions'
;;
pro | enterprise)
echo 'business editions'
;;
education | 'pro education' | 'pro for workstations')
# arm business iso 都没有 education, pro education, pro for workstations # arm business iso 都没有 education, pro education, pro for workstations
# 即使它的名字包含 EDU # 即使它的名字包含 EDU
# SW_DVD9_Win_Pro_10_22H2.31_Arm64_English_Pro_Ent_EDU_N_MLF_X24-05074.ISO # SW_DVD9_Win_Pro_10_22H2.31_Arm64_English_Pro_Ent_EDU_N_MLF_X24-05074.ISO
# en-us_windows_11_business_editions_version_25h2_arm64_dvd_8afc9b39.iso # en-us_windows_11_business_editions_version_25h2_arm64_dvd_8afc9b39.iso
case "$edition" in case "$arch_win" in
home | 'home single language') echo consumer ;; arm64) echo 'consumer editions' ;; # 只能从 consumer 获取
pro | enterprise) echo business ;; x64) echo 'business editions' ;; # iso 更小
education | 'pro education' | 'pro for workstations')
case "$arch_win" in
arm64) echo consumer ;;
x64) echo business ;; # iso 更小
esac
;;
# iot
'iot enterprise' | 'iot enterprise subscription') echo 'iot enterprise' ;;
# iot ltsc
'iot enterprise ltsc 2024' | 'iot enterprise subscription ltsc 2024') echo 'iot enterprise ltsc 2024' ;;
# ltsc
'enterprise ltsc 2024')
# arm64 的 enterprise ltsc 2024 要下载 iot enterprise ltsc 2024 iso
case "$arch_win" in
arm64) echo 'iot enterprise ltsc 2024' ;;
x64) echo 'enterprise ltsc 2024' ;;
esac
;;
esac esac
;; ;;
# iot
'iot enterprise' | 'iot enterprise subscription')
echo 'iot enterprise'
;;
# ltsc
'enterprise ltsc 2024')
case "$arch_win" in
arm64) echo "iot $edition" ;; # 只能从 iot ltsc iso 获取
x64) echo "$edition" ;;
esac
;;
# iot ltsc
'iot enterprise ltsc 2024' | 'iot enterprise subscription ltsc 2024')
echo 'iot enterprise ltsc 2024'
;;
esac esac
fi ;;
2019 | 2022 | 2025)
case "$edition" in
serverstandard | serverstandardcore | serverdatacenter | serverdatacentercore)
echo _
;;
esac
;;
esac
} }
get_label_vlsc() { get_label_vlsc() {
case "$version" in case "$version" in
10 | 11) # SW_DVD9_Win_Pro_11_25H2_Arm64_Arabic_Pro_Ent_EDU_N_MLF_X24-13113.iso
# SW_DVD5_WIN_ENT_LTSB_10_2015_64BIT_Arabic_MLF_X20-26578.ISO
# SW_DVD5_WIN_ENT_LTSB_2016_64BIT_Arabic_MLF_X21-07425.ISO
# SW_DVD5_WIN_ENT_LTSC_2019_64-bit_Arabic_MLF_X21-96407.ISO
# SW_DVD9_WIN_ENT_LTSC_2021_64BIT_ChnSimp_MLF_X22-84402.ISO
# SW_DVD9_WIN_ENT_LTSC_2024_64-bit_Arabic_MLF_X23-70037.ISO
# SW_DVD5_Win_10_IOT_Enterprise_2015_LTSB_64Bit_EMB_English_OEM_X20-20063.IMG
# SW_DVD5_Win10_IoT_Enterprise_LTSB_1607_64-bit_EMB_English_OEM_X21-05293.IMG
# SW_DVD9_Win_11_IoT_Enterprise_LTSC_24H2_64-Bit_English_X23-70076.ISO
10)
case "$edition" in case "$edition" in
pro | education | enterprise | 'pro education' | 'pro for workstations') echo pro ;; pro | education | enterprise | 'pro education' | 'pro for workstations') echo pro ;;
'enterprise 2015 ltsb') echo 'ent ltsb 10 2015' ;;
'enterprise 2016 ltsb') echo 'ent ltsb 2016' ;;
'enterprise ltsc 2019') echo 'ent ltsc 2019' ;;
'enterprise ltsc 2021') echo 'ent ltsc 2021' ;;
'iot enterprise 2015 ltsb') echo 'iot enterprise 2015 ltsb' ;; # √
'iot enterprise 2016 ltsb') echo 'iot enterprise ltsb 1607' ;; # √
'iot enterprise ltsc 2019') echo 'iot enterprise ltsc 2019' ;; # 没找到
'iot enterprise ltsc 2021') echo 'iot enterprise ltsc 2021' ;; # 没找到
esac esac
;; ;;
2025) 11)
echo SrvSTDCORE case "$edition" in
pro | education | enterprise | 'pro education' | 'pro for workstations') echo pro ;;
'enterprise ltsc 2024') echo 'ent ltsc 2024' ;;
'iot enterprise ltsc 2024' | 'iot enterprise subscription ltsc 2024') echo 'iot enterprise ltsc 24h2' ;; # √
esac
;; ;;
esac esac
} }
@@ -997,20 +1046,26 @@ get_windows_iso_link() {
: :
} }
get_page() { get_page_url() {
if [ "$arch_win" = arm64 ]; then local page=
echo arm
elif is_ltsc; then if is_ltsc; then
echo ltsc page=ntriver/ltsc
elif [ "$server" = 'server' ]; then elif [ "$server" = 'server' ]; then
echo server page=massgrave/server
else else
case "$version" in case "$version" in
10 | 11) 8 | 8.1 | 10 | 11)
echo "$version" page=ntriver/$version
;; ;;
esac esac
fi fi
case "$page" in
massgrave/server) echo https://massgrave.dev/windows-server-links ;;
massgrave/*) echo https://massgrave.dev/windows_${page#*/}_links ;;
ntriver/*) echo https://ntriver.org/download-windows-${page#*/} ;;
esac
} }
is_ltsc() { is_ltsc() {
@@ -1021,13 +1076,7 @@ get_windows_iso_link() {
label_msdn=$(get_label_msdn) label_msdn=$(get_label_msdn)
label_msdl=$(get_label_msdl) label_msdl=$(get_label_msdl)
label_vlsc=$(get_label_vlsc) label_vlsc=$(get_label_vlsc)
page=$(get_page) page_url=$(get_page_url)
if [ "$page" = server ]; then
page_url=https://massgrave.dev/windows-server-links
else
page_url=https://massgrave.dev/windows_${page}_links
fi
info "Find windows iso" info "Find windows iso"
echo "Version: $version" echo "Version: $version"
@@ -1035,7 +1084,7 @@ get_windows_iso_link() {
echo "Label msdn: $label_msdn" echo "Label msdn: $label_msdn"
echo "Label msdl: $label_msdl" echo "Label msdl: $label_msdl"
echo "Label vlsc: $label_vlsc" echo "Label vlsc: $label_vlsc"
echo "List: $page_url" echo "Page: $page_url"
echo echo
# 先判断是否能自动查找该版本 # 先判断是否能自动查找该版本
@@ -1043,7 +1092,7 @@ get_windows_iso_link() {
# 这样可以在输入错误 Edition 时例如 windows 11 enterprise ltsc 2021 # 这样可以在输入错误 Edition 时例如 windows 11 enterprise ltsc 2021
# 显示名称错误,而不是显示该版本不支持 arm # 显示名称错误,而不是显示该版本不支持 arm
if [ -z "$page" ] || { [ -z "$label_msdn" ] && [ -z "$label_msdl" ] && [ -z "$label_vlsc" ]; }; then if [ -z "$page_url" ] || { [ -z "$label_msdn" ] && [ -z "$label_msdl" ] && [ -z "$label_vlsc" ]; }; then
error_and_exit "Not support find this iso. Check if --image-name is wrong. Or set --iso manually." error_and_exit "Not support find this iso. Check if --image-name is wrong. Or set --iso manually."
fi fi
@@ -1056,26 +1105,32 @@ get_windows_iso_link() {
else else
http_to_host=$(get_scheme_and_host_by_url "$page_url") http_to_host=$(get_scheme_and_host_by_url "$page_url")
http_to_current_dir=$(dirname "$page_url") http_to_current_dir=$(dirname "$page_url")
curl -L "$page_url" |
tr -d '\n' | sed -e 's,<a ,\n<a ,g' -e 's,</a>,</a>\n,g' | # 使每个 <a></a> 占一行 curl -L "$page_url" | tr -d '\n' | # 合成一行
grep -Ei '\.(iso|img)</a>$' | # 找出是 iso 或 img 的行 if [[ "$page_url" =~ massgrave.dev ]]; then
# 提取文件名和链接 sed -e 's,<a ,\n<a ,g' -e 's,</a>,</a>\n,g' | # 使每个 <a></a> 占一行
grep -Ei '\.(iso|img)</a>$' | # 找出是 iso 或 img 的行
sed -E 's,<a href="?([^" ]+)"?.+>(.+)</a>,\2 \1,' # 提取文件名和链接
else
sed -e 's,<td><strong>,\n<td><strong>,g' -e 's,</a>,</a>\n,g' | # 使每个镜像占一行
grep -Ei '\.(iso|img)</strong>' | # 找出是 iso 或 img 的行
sed -E 's,<td><strong>([^<]+).+<a href="?([^" ]+)"?.+,\1 \2,' # 提取文件名和链接
fi |
# 如果链接是 / 开头,则补全域名 # 如果链接是 / 开头,则补全域名
# 如果链接非 https:// 开头,则补全域名和目录 # 如果链接非 https:// 开头,则补全域名和目录
sed -E -e 's,<a href="?([^" ]+)"?.+>(.+)</a>,\2 \1,' \ sed -E "s, (/), $http_to_host\1," |
-e "s, (/), $http_to_host\1," | awk '{if ($2 !~ /^https?:\/\//) $2 = "'$http_to_current_dir/'" $2; print}' |
awk '{if ($2 !~ /^https?:\/\//) $2 = "'$http_to_current_dir/'" $2; print}' >$tmp/win.list
# 如果不是 ltsc ,应该先去除 ltsc 链接,否则最终链接有 ltsc 的 # 如果不是 ltsc ,应该先去除 ltsc 链接,否则最终链接有 ltsc 的
# 例如查找 windows 10 iot enterprise,会得到 # 例如查找 windows 10 iot enterprise,会得到
# en-us_windows_10_iot_enterprise_ltsc_2021_arm64_dvd_e8d4fc46.iso # en-us_windows_10_iot_enterprise_ltsc_2021_arm64_dvd_e8d4fc46.iso
# en-us_windows_10_iot_enterprise_version_22h2_arm64_dvd_39566b6b.iso # en-us_windows_10_iot_enterprise_version_22h2_arm64_dvd_39566b6b.iso
# sed -Ei 和 sed -iE 是不同的 if is_ltsc; then
if is_ltsc; then grep -Ei '_lts[bc]_'
sed -Ei '/ltsc|ltsb/!d' $tmp/win.list else
else grep -Ei -v '_lts[bc]_'
sed -Ei '/ltsc|ltsb/d' $tmp/win.list fi >$tmp/win.list
fi
get_windows_iso_link_inner get_windows_iso_link_inner
fi fi
@@ -1090,6 +1145,29 @@ get_shortest_line_by_field() {
awk "(NR == 1 || length(\$$field) < length(field)) { line = \$0; field = \$$field } END { print line }" awk "(NR == 1 || length(\$$field) < length(field)) { line = \$0; field = \$$field } END { print line }"
} }
get_best_windows_iso_line() {
local lines
lines=$(cat)
# 在所有符合的 iso 中
# 先选择 win10/11 大版本更新的 (version 26h1) 或者有 sp 版本的 (sp1, windows_8.1_with_update_)
# 再选择有日期更新的 (updated_july_2026)
# 再选择 vl
# 再按版本号排序选择最新版
# 但是也有例外
# zh-cn_windows_server_2019_x64_dvd_19d65722.iso 2022-11-15
# cn_windows_server_2019_updated_april_2021_x64_dvd_a6dae187.iso 2021-04-20
for key in '(version|sp[0-9]|update)' 'updated' 'vl'; do
if grep_lines=$(grep -E "_${key}_" <<<"$lines"); then
lines=$grep_lines
fi
done
echo "$lines" | sort -Vr | head -1
}
get_windows_iso_link_inner() { get_windows_iso_link_inner() {
regexs=() regexs=()
@@ -1099,14 +1177,29 @@ get_windows_iso_link_inner() {
label_msdn= label_msdn=
fi fi
for lang in $langs; do for lang in $langs; do
regex= # en_windows_vista_sp2_x64_dvd_342267.iso
# cn_windows_vista_with_sp2_x64_dvd_x15-36322.iso
# en_windows_8_x64_dvd_915440.iso
# en_windows_8.1_pro_vl_with_update_x64_dvd_6050880.iso
# en_windows_8.1_with_update_x64_dvd_6051480.iso
# en_windows_8.1_n_with_update_x64_dvd_6051677.iso
# en-us_windows_10_iot_enterprise_version_22h2_arm64_dvd_39566b6b.iso
# en-us_windows_11_consumer_editions_version_26h1_updated_july_2026_x64_dvd_f69a9a1e.iso
# en-us_windows_server_2025_updated_july_2026_x64_dvd_4e6f5a42.iso
local prefix=
for i in ${lang} windows ${server} ${version} ${label_msdn}; do for i in ${lang} windows ${server} ${version} ${label_msdn}; do
if [ -n "$i" ]; then if [ -n "$i" ]; then
regex+="${i}_" prefix+="${i}_"
fi fi
done done
regex+=".*${arch_win}.*.(iso|img)"
regexs+=("$regex") # 用于准确匹配,例如防止 2012 匹配到 2012 r2
# 首先匹配 label 后面紧接着这些关键字的
# 然后匹配 label 后面紧接着 x64/arm64 的
# 最后模糊匹配
regexs+=("${prefix}(version|vl|with|updated|sp[0-9])_.*${arch_win}.*\.(iso|img)")
regexs+=("${prefix}${arch_win}.*\.(iso|img)")
regexs+=("${prefix}.*${arch_win}.*\.(iso|img)")
done done
fi fi
@@ -1118,8 +1211,14 @@ get_windows_iso_link_inner() {
# 先判断 full_lang 是否为空 # 先判断 full_lang 是否为空
# 因为假如用户输入的 lang 不正确,full_lang 就为空,正则表达式就无法只匹配当前语言 # 因为假如用户输入的 lang 不正确,full_lang 就为空,正则表达式就无法只匹配当前语言
if [ -n "$label_vlsc" ] && [ -n "$full_lang" ]; then if [ -n "$label_vlsc" ] && [ -n "$full_lang" ]; then
regex="sw_?dvd[59]_win_?${label_vlsc}_?${version}.*${arch_win_vlsc}_${full_lang}.*.(iso|img)" regexs+=("sw_?dvd[59]_win_?${label_vlsc}_?${version}_.*${arch_win_vlsc}.*_${full_lang}.*.(iso|img)")
regexs+=("$regex") regexs+=("sw_?dvd[59]_win_?${version}_${label_vlsc}_?.*${arch_win_vlsc}.*_${full_lang}.*.(iso|img)")
# LTSC 没有 windows 主版本号
# SW_DVD5_WIN_ENT_LTSB_10_2015_64BIT_Arabic_MLF_X20-26578.ISO # 将 ENT_LTSB_10_2015 视为 label
# SW_DVD5_WIN_ENT_LTSB_2016_64BIT_Arabic_MLF_X21-07425.ISO # 将 ENT_LTSB_2016 视为 label
if is_ltsc; then
regexs+=("sw_?dvd[59]_win_?${label_vlsc}_?.*${arch_win_vlsc}.*_${full_lang}.*.(iso|img)")
fi
fi fi
# 查找 # 查找
@@ -1127,10 +1226,16 @@ get_windows_iso_link_inner() {
regex=${regex// /_} regex=${regex// /_}
echo "looking for: $regex" >&2 echo "looking for: $regex" >&2
if line=$(grep -Ei "^$regex " "$tmp/win.list" | get_shortest_line_by_field 1 | grep .) && local matched_lines
iso=$(awk '{print $2}' <<<"$line" | grep .); then if matched_lines=$(grep -Ei "^$regex " "$tmp/win.list"); then
echo "Selected: $line" >&2 info "ISO Matched"
return cat -n <<<"$matched_lines" >&2
if line=$(echo "$matched_lines" | get_best_windows_iso_line | grep .) &&
iso=$(awk '{print $2}' <<<"$line" | grep .); then
info "ISO Selected"
echo " $line" >&2
return
fi
fi fi
done done
@@ -1531,7 +1636,8 @@ Continue?
else else
iso_is_tested=false iso_is_tested=false
if $auto_find_iso; then if $auto_find_iso; then
if test_url_grace "$iso" iso 2>/dev/null; then # 目前自动获取 iso 肯定不是直连,因此先关闭直连测试
if false && test_url_grace "$iso" iso 2>/dev/null; then
iso_is_tested=true iso_is_tested=true
else else
# 需要用户输入 massgrave.dev 直链 # 需要用户输入 massgrave.dev 直链
@@ -1548,6 +1654,8 @@ Continue?
IFS= read -r -p "Direct Link: " iso IFS= read -r -p "Direct Link: " iso
if [ -z "$iso" ]; then if [ -z "$iso" ]; then
error_and_exit "ISO Link is empty." error_and_exit "ISO Link is empty."
elif ! grep -Eiq '^https?://' <<<"$iso"; then
error_and_exit "ISO Link is invalid."
fi fi
fi fi
fi fi