Как смонтировать несколько разделов EFI? - PullRequest
0 голосов
/ 01 апреля 2020

Я пытаюсь создать Applescript-Obj c для монтирования нескольких разделов EFI, но я не могу смонтировать разделы EFI на внешних дисках только те, которые находятся на внутреннем диске, что я делал до сих пор это:

set a to do shell script "diskutil list | grep EFI | grep -o -e disk[0-9]s[0-9]"
set b to do shell script "diskutil info " & a & " | awk '/Identifier/' | grep -o -e disk[[:digit:]]*"
set c to do shell script "diskutil info " & b & "| grep 'Media Name' | awk /'Name:/{print$5,$6}'"
choose from list c with prompt "Multiple EFI partitions found:"
display alert "Do you want to mount the EFI partition?" buttons {"Yes", "No"} default button 1
set response to button returned of the result
if response = "Yes" then
    do shell script "diskutil mount " & a with administrator privileges
    display alert result
end if

Примечание: когда пользователь спрашивает, я хочу, чтобы отображалось имя диска, а не что-то вроде: '' disk0s1 '' Заранее спасибо!

1 Ответ

1 голос
/ 02 апреля 2020

Я написал служебный апплет для монтирования / демонтажа EFI, а go, который использует NSAlert со списком, чтобы попытаться избежать смерти в диалоге, типичном для AppleScripts. Из этого сценария я извлек сценарий и добавил имена дисков в начальный диалог - благодаря предупреждениям он немного длиннее вашего фрагмента, но там должно быть что-то, что вы можете использовать:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property alertHeader : "                          --- CAUTION ---" & return & "This utility works with EFI boot partitions -" & return & "Administrator authorization will be required."
property resources : "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/"
property leadText : "                  "
property identifiers : missing value -- this will be a list of the EFI partition identifiers, e.g. {disk0s1}

on run -- example can be run as app and from Script Editor
    if current application's NSThread's isMainThread() as boolean then
        doStuff()
    else
        my performSelectorOnMainThread:"doStuff" withObject:(missing value) waitUntilDone:true
    end if
end run

on doStuff() -- the main stuff
    set theDisks to setup() -- set up properties and get disks with EFI partitions, e.g. {/dev/disk0}
    set reply to {button:missing value, answer:""} -- preset a previous empty dialog result
    repeat -- forever
        set theAnswer to answer of reply -- use previous
        set reply to (showAlert given settings:{title:"EFI [un]Mounter", message:alertHeader, information:"EFI partitions have been found on the following disks:" & return & return & theDisks & return & "The EFI partition of the specified disk will be [un]mounted." & return & "Enter the disk identifier or select one from the menu:", answer:theAnswer, icon:(resources & "AlertCautionIcon.icns"), buttons:{"Cancel", "Mount", "Unmount", "More Info"}})
        if button of reply is "Cancel" then error number -128
        set diskID to checkID(answer of reply)
        if diskID is not missing value then -- found it
            if button of reply is "More Info" then
                set reply to moreInfo(answer of reply) -- result of the moreInfo dialog
                if button of reply is not "Change" then exit repeat
            else
                exit repeat
            end if
        else -- try again
            beep
            set answer of reply to ""
        end if
    end repeat
    processEFI(button of reply, diskID)
end doStuff

to processEFI(command, diskID) -- mount or unmount the specified disk - admin authorization will be needed
    log diskID
    try
        set command to (do shell script "echo " & command & " | tr [:upper:] [:lower:]")
        if command is not in {"mount", "unmount"} then error "The processEFI handler received an invalid command."

        set theResult to (do shell script "diskutil " & command & " /dev/" & diskID with administrator privileges)
        if command is "mount" then tell application "Finder" -- show it
            make new Finder window to ("/Volumes/EFI" as POSIX file)
            activate
        end tell
        display notification theResult
        delay 2
    on error errmess
        log errmess
        showAlert given settings:{title:"EFI [un]Mounter", message:return & "There was an error processing the partition.", information:errmess, icon:(resources & "AlertCautionIcon.icns")}
    end try
end processEFI

on moreInfo(diskID) -- get more information about the specified disk identifier
    set infoText to ""
    set diskName to (do shell script "diskutil info " & diskID & " | grep 'Media Name' | awk '{print substr($0,index($0,$5))}'")
    if diskName is "" then
        set diskName to "the following disk"
    else
        set diskName to "disk " & quoted form of diskName
    end if
    repeat with aParagraph in paragraphs of (do shell script "diskutil list " & diskID)
        if aParagraph starts with leadText then -- trim information text
            if (paragraph -2 of infoText does not start with leadText) then set infoText to infoText & leadText & trimWhitespace(text 1 thru -1 of contents of aParagraph) & return
        else if aParagraph does not start with "   #:" then -- don't include header text
            if length of aParagraph is less than 56 then
                set infoText to infoText & aParagraph & return
            else -- trim description text
                set infoText to infoText & space & space & space & text 1 thru 6 of aParagraph & tab & trimWhitespace(text 7 thru 56 of aParagraph)
                set infoText to infoText & return
            end if
        end if
    end repeat
    set reply to (showAlert given settings:{title:"EFI [un]Mounter", message:alertHeader, information:"The EFI partition of " & diskName & " will be [un]mounted:" & return & return & infoText, icon:(resources & "AlertCautionIcon.icns"), buttons:{"Cancel", "Mount", "Unmount", "Change"}})
    if button of reply is "Cancel" then error number -128
    return {button:button of reply, answer:diskID}
end moreInfo

to showAlert given settings:arguments -- show a custom alert
    set arguments to arguments & {title:"", message:"Alert", information:"", answer:missing value, icon:"", buttons:{"OK"}} -- a record is used for input parameters, unspecified keys will use default values
    tell current application's NSAlert's alloc's init()
        if (icon of arguments) as text is "Critical" then -- everything else is NSInformationalAlertStyle
            set its alertStyle to current application's NSCriticalAlertStyle
        else -- use the contents of an image file - informational icon will be used if no image or file (missing value)
            set its icon to current application's NSImage's alloc's initByReferencingFile:((icon of arguments) as text)
        end if
        set its |window|'s title to (title of arguments) as text
        set its messageText to (message of arguments) as text -- the bold text
        set its informativeText to (information of arguments) as text -- the normal text
        set buttonList to my (setButtons for it from (buttons of arguments))
        if (answer of arguments) is not missing value then
            set its |window|'s autorecalculatesKeyViewLoop to true
            set accessory to my (makeComboAccessory for it)
            set accessory's stringValue to answer of arguments
        end if
        activate me
        set response to ((its runModal) as integer) - 999 -- get index - 1000 is rightmost button
    end tell
    if answer of arguments is not missing value then set answer of arguments to (accessory's stringValue) as text
    return {button:item response of buttonList, answer:answer of arguments} -- returns a record: {button:(button title), answer:(text field value, or 'missing value' if not used)}
end showAlert

to setButtons for alert from buttons -- set buttons for the alert - filters for blanks and duplicates; returns a list of the button titles (left-to-right)
    set {buttonList, theButton} to {{}, missing value}
    repeat with aButton in reverse of (buttons as list) -- match dialog order
        set aButton to aButton as text
        if aButton is not in buttonList and aButton is not in {missing value, ""} then -- filter
            set theButton to (alert's addButtonWithTitle:aButton)
            set end of buttonList to aButton
        end if
    end repeat
    if buttonList is {} then -- better have at least one
        set theButton to alert's addButtonWithTitle:"OK"
        set end of buttonList to "OK"
    end if
    set alert's |window|()'s initialFirstResponder to theButton -- the last (leftmost) one
    return buttonList
end setButtons

to makeComboAccessory for alert -- make and return a comboBox accessory view for the alert
    tell (current application's NSComboBox's alloc's initWithFrame:{{0, 0}, {288, 28}})
        set its completes to true
        set its hasVerticalScroller to true
        set its placeholderString to "a disk identifier, for example disk0" -- arbitrary  
        repeat with anItem in identifiers -- populate the combo box with the disks with EFI partitions
            set here to offset of "s" in (reverse of characters of anItem) as text
            set anItem to text 1 thru -(here + 1) of anItem -- strip off partition
            (its addItemWithObjectValue:anItem)
        end repeat
        set alert's accessoryView to it
        return it
    end tell
end makeComboAccessory

to checkID(diskID) -- check the disk identifier against the EFI partitions - returns the EFI partition, or missing value if not found
    if diskID is not "" then repeat with anItem in identifiers
        set anItem to anItem as text
        set here to offset of "s" in (reverse of characters of anItem) as text -- partition index
        if text 1 thru -(here + 1) of anItem is first word of diskID then return anItem
    end repeat
    return missing value
end checkID

to trimWhitespace(someText) -- trim whitespace characters from the beginning and end of a string
    set someText to someText as text
    if someText is "" then return ""
    set whiteSpace to {space, tab, return, linefeed}
    repeat until the first character of someText is not in whiteSpace
        if (count someText) is 1 then return ""
        set someText to text 2 thru -1 of someText
    end repeat
    repeat until the last character of someText is not in whiteSpace
        if (count someText) is 1 then return ""
        set someText to text 1 thru -2 of someText
    end repeat
    return someText
end trimWhitespace

to setup() -- set up properties and stuff
    set {theDisks, identifiers} to {"", {}}
    try
        repeat with aPartition in paragraphs of (do shell script "diskutil list | grep 'EFI EFI' | grep -E -o 'disk[0-9]?[0-9]s[0-9]?[0-9]'") -- just EFI partitions named EFI
            set aDisk to first paragraph of (do shell script "diskutil list " & aPartition)
            if aDisk does not contain "disk image" then -- don't add disk images
                set diskName to (do shell script "diskutil info " & text 1 thru -3 of aPartition & " | grep 'Media Name' | awk '{print substr($0,index($0,$5))}'")
                if diskName is in {"", missing value} then
                    set diskName to ""
                else
                    set diskName to "(" & diskName & ")"
                end if
                set theDisks to theDisks & tab & text 1 thru 11 of aDisk & space & diskName & return
                set end of my identifiers to aPartition
            end if
        end repeat
        if (count identifiers) < 1 then error "No EFI partitions were found."
        return theDisks -- returns the disks found with EFI partitions (for the initial dialog)
    on error errmess
        log errmess
        showAlert given settings:{title:"EFI [un]Mounter", message:return & errmess, icon:(resources & "AlertStopIcon.icns")}
        error number -128
    end try
end setup
...