Найти загрузчик Windows на разделе жесткого диска, дело не очень сложное:
1. Надо проверить файловую систему раздела, она должна быть FAT32 или NTFS
2. Проверить наличие файла
ntldr
(Windows XP и ранее) или bootmgr
(Windows Vista и позднее) в корне раздела. Windows XP и старше, при установке по умолчанию, записывают файл ntldr
в корень системного раздела, а более новые - создают отдельный загрузочный раздел, в корне которого лежит bootmgr
. Для чего? Например, для создания своего скрипта автоматической настройки загрузчика Grub или Syslinux
Я недавно писал о том, как узнать файловую систему раздела (диска) в Linux Копия. В данном случае действовать будем примерно также.
Обработать вывод команды
blkid
(вывод данных о блочных устройствах) можно в цикле for
:echo "Find Windows loaders..."
IFS=$'\n'
for DEVDATA in $(blkid); do
...
done
Перед циклом необходимо установить значение переменной
IFS
, как \n
(перенос строки)IFS
- переменная, задающая разделители полей при работе со строками в shell, по умолчанию разделители это табуляция, перенос строки и пробел, если не установить ее значение, как "только перенос строки", то строка с описанием каждого раздела (например, /dev/sda1: UUID="68DF-FF87" TYPE="vfat" PARTUUID="00003214-01"
) распадется на части, что поломает алгоритм.В цикле
for
:1. Вытаскиваем в переменную
VOL
нужные данные - путь к устройству и файловую систему:VOL=`echo "$DEVDATA" |sed -n 's/\(.*:\).* TYPE=\"\([^\"]*\)\".*/\1\2/p'`
Для вышеуказанного
/dev/sda1
получится строка /dev/sda1:vfat
2. Получаем путь к устройству и тип файловой системы отдельно в переменные, соответственно,
VOLNAME
и VOLFS
.VOLNAME=`echo "$VOL"|awk -F ":" '{print $1}'`
VOLFS=`echo "$VOL"|awk -F ":" '{print $2}'`
Параметр
-F ":"
устанавливает двоеточие в качестве разделителя полей awk
.3. Далее, проверяем, не пуста ли строка в переменной
VOLFS
, и проверяем ее значение. Если VOLFS
равна ntfs
или vfat
, то запускаем функцию find_loader()
, проверяющую наличие загрузчика в корне соответствующего раздела. Если файловая система раздела другая - выводится сообщение, что это не Windows-раздел.if [ -n "$VOLFS" ]; then
if [[ "$VOLFS" == "ntfs" || "$VOLFS" == "vfat" ]];then
find_loader $VOLNAME $VOLFS
else
echo "$VOLNAME not windows volume"
fi
fi
Можно было бы еще исключать разделы FAT16, но решил не загромождать скрипт лишней проверкой.
В функцию
find_loader()
передаются два параметра: путь к устройству (разделу) и его файловая система.1. Заведем переменную-флаг, указывающую, был ли раздел временно смонтирован
TMPMOUNT=0
2. Получаем выхлоп команды
mount
. grep
'ом фильтруем вывод по соответствующему разделу, с помощью awk
вытаскиваем точку монтирования.MOUNTPOINT=`mount|grep -w "$1"|awk '{print $3}'`
3. Если переменная
MOUNTPOINT
пустая, раздел не смонтирован. Создаем временную точку монтирования, пытаемся смонитровать раздел, если получилось - устанавливаем TMPMOUNT=1
, в переменную MOUNTPOINT
записываем временную точку монтирования и приступаем к поиску загрузчика, если не получилось - выходим из функции:if [ -z "$MOUNTPOINT" ]; then
mkdir -p "/tmp/tmpmount"
mount -t "$2" "$1" "/tmp/tmpmount"
if [ $? -ne 0 ]; then
echo "$1 not mounted"
return
fi
MOUNTPOINT="/tmp/tmpmount"
TMPMOUNT=1
fi
Примечание: ключ
-p
команды mkdir
позволяет создать путь вместе со всеми подкаталогами, а если путь уже создан, то команда mkdir
не выдаст ошибки, что путь уже существует.Надо обратить внимание на то, что Windows нечувствительна к регистру имен файлов, так что загрузчик может быть и
bootmgr
и BOOTMGR
, и даже BoOtMgR
(аналогично и ntldr
). Поэтому придется воспользоваться командой find
.find <path> -maxdepth 1 -iname <filename>
где:
<path>
- путь к каталогу, с которого начинать поиск-maxdepth
- глубина поиска в подкаталогах (начиная с указанного в <path>
, 1
- только каталог <path>
без подкаталогов).-iname
- игнорировать регистр имени файла<filename>
- имя файла (или маска), который будем искать.В данном случае надо обязательно установить
-maxdepth 1
, иначе будут большие тормоза, а при отмонтировании возможны глюки.4. Ищем загрузчик Vista и выше и сохраняем выхлоп в переменную
FOUND
:FOUND=`find "$MOUNTPOINT" -maxdepth 1 -iname "bootmgr"`
5. Если нашли (переменная
FOUND
не пустая), выводим соответствующее сообщение, если нет - ищем загрузчик Windows XP, и выводим сообщение в зависимости от того, нашли или нет:if [ -n "$FOUND" ];then
echo "$1: found bootmgr (Windows Vista and newer)"
else
#ntldr - Win XP and older
FOUND=`find "$MOUNTPOINT" -maxdepth 1 -iname "ntldr"`
if [ -n "$FOUND" ];then
echo "$1: found ntldr (Windows XP and older)"
else
echo "$1: Windows loader not found"
fi
fi
6. Проверяем флаг
TMPMOUNT
, если он был установлен в 1
, отмонтируем временно смонтированный раздел:if [ $TMPMOUNT -eq 1 ]; then
sleep 1
umount "/tmp/tmpmount"
fi
Запуск на тестовой машине с разделами FAT32/NTFS, но без установленной Windows:
Запуск на машине с установленной Windows 7:
Запуск на машине с установленной Windows XP
На GitHub
На PasteBin
1. Определение файловой системы раздела диска в Linux Копия
2. Команда find в Linux Копия
Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2019/03/27/skri