Найти загрузчик 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
1. Определение файловой системы раздела диска в Linux Копия
2. Команда find в Linux Копия