BASH:从 diskutil 输出中查找分区

BASH:从 diskutil 输出中查找分区

我正在尝试搜索列出本地驱动器的命令的输出,以在启动硬盘上找到名为 EFI 的分区。

我写了一个非常肮脏的单行代码,因为我似乎无法弄清楚如何有效地找到主硬盘(大概总是 Macintosh HD),然后找出同一驱动器上的 EFI 分区,然后从那里找到 Macintosh HD 驱动器上 EFI 分区的磁盘#s# IDENTIFIER。

标准输出diskutil list是这样的

$ diskutil list
/dev/disk0
#:                       TYPE NAME                    SIZE       IDENTIFIER
0:      GUID_partition_scheme                        *500.1 GB   disk0
1:                        EFI EFI                     209.7 MB   disk0s1
2:                  Apple_HFS Macintosh HD            499.1 GB   disk0s2
3:                 Apple_Boot Recovery HD             784.2 MB   disk0s3

/dev/disk1
#:                       TYPE NAME                    SIZE       IDENTIFIER
0:      GUID_partition_scheme                        *1.5 TB     disk1
1:                        EFI EFI                     209.7 MB   disk1s1
2:                  Apple_HFS Data                    1.5 TB     disk1s2

以下是我一直在使用的肮脏的单行代码。有没有更好的方法可以做到这一点? 

diskutil mount $(diskutil list | grep -i 'Macintosh\ HD' | awk '{print $6}' | grep -i 'disk0s')

答案1

我假设 /dev/disk0 始终是“主”硬盘,对吗?如果不是,而您确实想在名为“Macintosh HD”的磁盘上找到 EFI 分区,那么您的一行代码几乎是正确的。

对我来说,$6 返回“GB”,并且我还假设 EFI 分区始终是该特定磁盘的第一个分区,因此请尝试:

diskutil list | grep 'Macintosh HD' | awk '{print $(NF)}' | sed 's/s[0-9]/s1/'

或者使用更多的 awk 技巧(为了更好的效果):

diskutil list | awk '/Macintosh HD/ { sub(/s[0-9]/, "s1", $(NF)); print $(NF) }'

答案2

您可以尝试使用以下命令检测主块设备:

mount | awk '/on \/ / {print $1}'

我似乎找不到检测主卷的方法,因为我的输出没有列出它们,我只能看到主块设备和一些内容描述:

/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *251.0 GB   disk0
   1:                        EFI EFI                     209.7 MB   disk0s1
   2:          Apple_CoreStorage                         250.1 GB   disk0s2
   3:                 Apple_Boot Recovery HD             650.0 MB   disk0s3
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:                  Apple_HFS Macintosh HD           *249.8 GB   disk1
                                 Logical Volume on disk0s2
                                 XXXXXXXX-XXXX-XXXX-XXXX-7C6C089FXXXX
                                 Unencrypted

就我而言,我可以轻松使用,awk '/Logical Volume/ {print $NF}'但更强大的脚本会考虑 Mac 版本来检查所有可能的情况。

顺便说一句,我在 2014 年中期 MBP 15" 上使用的是 Yosemite 10.10.4。

答案3

好吧,这还没有完成,但是我没有时间了。

因此,我使用 df 命令,因为我知道这将在末尾有挂载点。然后我用斜线换行符模式对其进行 grep。然后我想删除第一个空格符号后的所有内容。但是现在删除不起作用。我真的不知道我做错了什么,我现在必须开始工作,但也许你可以改进 bash 功能的删除。抱歉,没有时间查阅手册来找出我的错误。但我们快到了:

更正:

foo=$(df -h | grep -e ' /$'); loo=${foo%%" "*}; echo $loo

现在它起作用了。试试看 :)

编辑:哦,我刚刚意识到我正在使用 lvg,因此 disk0s[0-4] 将被转换为 disk1。因此,请测试它并告诉我这是否正确地向您显示了您未使用 lvg 的正确磁盘。

编辑 2:仍然不适用于加密逻辑卷组,但如果你可以在没有 FileVault 的情况下测试这个,它应该可以工作

foo=$(mount | grep -e ' / '); foo=${foo%%" "*}; diskutil list | grep "[0-99]:" | grep ${foo##"/dev/"} | grep EFI)

这将在以 root 身份安装的磁盘上查找 EFI,因此通常是 MacintoshHD

编辑 3:这真是一个很棒的消磨工作时间的好方法。好的,我想这应该能给你正确的答案。即使它是 FileVault 加密的,它也可以这样做。

#!/bin/bash

maindrive=$(mount | grep -e " / ")
maindrive_exact=${maindrive%%" "*}
maindrive_reduced=${maindrive_exact##"/dev/"}

if [ "$(diskutil list | grep Unlocked)" = "" ]
        then
                diskline=$(diskutil list | grep "[0-99]:" | grep $maindrive_reduced | grep EFI)
                diskline_cut1=${diskline##*"B "}
                diskline_cut2=${diskline##*" "}
                echo "/dev/$diskline_cut2"

        else
                alldisk=$(diskutil list)
                alldisk_cut1=${alldisk##*${maindrive_reduced}}
                alldisk_cut2=${alldisk_cut1#*"Logical Volume on "}
                alldisk_cut3=${alldisk_cut2%%" "*}
                echo /dev/$alldisk_cut3
fi

因此,这应该会为您提供与根文件夹 MacintoshHD 位于同一硬盘上的 EFI 分区。

编辑 4(希望是最终版本)

#!/bin/bash

maindrive=$(mount | grep -e " / ")
maindrive_exact=${maindrive%%" "*}
maindrive_reduced=${maindrive_exact##"/dev/"} 


function getdisknumber {
diskline=$(diskutil list | grep "[0-99]:" | grep $maindrive_reduced | grep EFI)
                diskline_cut1=${diskline##*"B "}
                diskline_cut2=${diskline##*" "}
                echo "/dev/$diskline_cut2"
}

if [ "$(diskutil list | grep Unlocked)" = "" ] 
    then 
        getdisknumber   
    else 
        alldisk=$(diskutil list)
        alldisk_cut=${alldisk#*${maindrive_reduced}}
        alldisk_cut=${alldisk_cut#*"Logical Volume on "}
        alldisk_cut=${alldisk_cut%%" "*}
        alldisk_cut=${alldisk_cut%s*}
        maindrive_reduced=$alldisk_cut
        getdisknumber
fi

以下是解释

Okay, as ask in the comment, the explanation what %%,%,##,# means. 
All those symbols cut out information of a string.
%%pattern cuts out the biggest pattern matching part to the right.
%pattern cuts out the smallest pattern matching part to the right.
##pattern cuts out the biggest pattern matching part to the left
#pattern cuts out the smallest pattern matching part to the left

脚本的 else 部分现在尝试在遇到 FileVault 创建的加密卷时找到正确的硬盘。然后,该函数将该硬盘细分为该硬盘上的磁盘信息,并寻找 EFI 作为关键字。

这是关于在 bash 中剪切字符串的链接 剪断琴弦

编辑 5:好的。此脚本的另一个迭代。非常非常基础。

#!/bin/bash

## Find the main hard drive

maindrive=$(mount | grep -e " / ")
maindrive=${maindrive#/dev/}
maindrive=${maindrive%%" "*}


## Checking for FileVault

if [ "" != "$(diskutil list /dev/disk1 | grep "Unlocked Encrypted")" ]
        then
                maindrive=$(diskutil list | grep "Logical Volume on")
                maindrive=${maindrive#*"Logical Volume on "}
                maindrive=${maindrive%s*}
fi


## Checking for EFI

EFI_DRIVE=$(diskutil list /dev/$maindrive | grep EFI)
EFI_DRIVE=${EFI_DRIVE##*" "}
echo "/dev/$EFI_DRIVE"

为了完整起见,这是我的磁盘工具列表:

/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *250.1 GB   disk0
   1:                        EFI EFI                     209.7 MB   disk0s1
   2:          Apple_CoreStorage                         249.2 GB   disk0s2
   3:                 Apple_Boot Recovery HD             650.0 MB   disk0s3
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:                  Apple_HFS Macintosh HD           *248.8 GB   disk1
                                 Logical Volume on disk0s2
                                 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                                 Unlocked Encrypted

当我运行脚本时,会发生以下情况:

Joes-MacBook-Pro:EFI_Script joe$ chmod +x EFI_Script
Joes-MacBook-Pro:EFI_Script joe$ ./EFI_Script
/dev/disk0s1
Joes-MacBook-Pro:EFI_Script joe$

我已经思考过为什么到目前为止它对你不起作用。所以,基本上,如果这也不起作用,我需要你提供两条信息。首先,我需要知道你的“ mount ”命令的输出。我的输出如下:

Joes-MacBook-Pro:EFI_Script joe$ mount
/dev/disk1 on / (hfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)

如您所见,它确实给了我“disk1”上的挂载点“/”。我只是假设,如果 FileVault 关闭,它会为您提供 disk0 上的挂载点。但也许我错了,我的系统上没有关闭 FileVault 的系统。因此,如果您的挂载点也在 disk1 上,而 EFI 在 disk0 上,它应该返回空或仅返回 /dev/,因为这是我手动添加的。另一方面,如果我没记错的话,您在 disk1 上也有一个 EFI 分区。

无论如何,我需要的第二件事是使用命令“bash -x script”运行此脚本,以便它在运行时显示其执行的操作。这样,我们就可以看到哪里出了问题。

无论如何,我希望它能正常工作,我们不必费这么大劲。但如果不行,我们必须想出另一种方法来找到主硬盘。

无论如何,测试一下吧。干杯!

相关内容