Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

AppleScript for selecting local volumes to unmount System
Note: An updated version of this script (in fact two new scripts) has been posted as a new hint. These new scripts take into account many of the comments posted below. Please see the new hint to find the improved version.

Here's an AppleScript that presents a dialog box listing mounted local volumes, one or more of which can be selected for unmounting. Some solutions for doing this either require the use of additional system resources or are offered commercially. This AppleScript is free, of course. Iíve only tested it in Lion so far. I recommend that you set up a keyboard shortcut that launches the AppleScript either as part of a Mac OS X Automator Service, or from the Script menu, which (in Lion) can be configured using the Keyboard preferences.
set alldisks to paragraphs of (do shell script "df -hlg | awk -F/ '/disk*/ {print $5}'")
try
   set item 1 of alldisks to ((characters 1 thru -2 of (path to startup disk as string)) as text)
on error
   set alldisks to {((characters 1 thru -2 of (path to startup disk as string)) as text)}
end try

set dur to {}
repeat with m in alldisks
   considering case
       if m is not in {"MobileBackups"} then
           set dur to dur & m
       end if
   end considering
end repeat

set devnames to paragraphs of (do shell script "df -k | awk -F/ '/disk*/ {print $3}'")
set t to {}
repeat with s in devnames
   set t to t & (word 1 of s)
end repeat

set the keylist to dur
set the foundDisks to t
set answer_list to {}

repeat with the_answer in keylist
   set theIndex to my CollectUniqueItemIndex(keylist, (the_answer as string))
    set theValue to item theIndex of foundDisks
   activate
   --set answer_list to answer_list & return & ((the_answer & ":" & space & theValue) as string)
   --set answer_list to answer_list & ((the_answer & ":" & space & theValue) as string)
   set answer_list to answer_list & (the_answer as string)
end repeat


set your_selected_device_id to choose from list answer_list with prompt "Please choose one or more volumes to be unmounted." with multiple selections allowed
repeat with b in your_selected_device_id
   set theIndex to my CollectUniqueItemIndex(answer_list, (b as string))
    set theValue to item theIndex of foundDisks
   --display dialog "The device name of a volume you selected is:" & space & "\"" & theValue & "\"." & space & "Are you sure you want to unmount it?"
   try
       do shell script "diskutil unmount /dev/" & theValue
   on error the error_message number the error_number
       display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
    end try
   
end repeat

on CollectUniqueItemIndex(theList, theItem) -- the Item can be string, number, constant, app object or list    
   local aListMember
   repeat with i from 1 to (count theList)
        set aListMember to item i of theList
       if aListMember = theItem then
           set theIndex to i
           exit repeat
       end if
   end repeat
   return theIndex
end CollectUniqueItemIndex

[kirkmc adds: This is a very nice script, works as advertised.]
    •    
  • Currently 4.50 / 5
  You rated: 3 / 5 (6 votes cast)
 
[7,236 views]  

AppleScript for selecting local volumes to unmount | 24 comments | Create New Account
Click here to return to the 'AppleScript for selecting local volumes to unmount' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
AppleScript for selecting local volumes to unmount
Authored by: llee on May 03, '12 08:17:14AM

Here's another related one that I contributed as a response to another topic.

http://hints.macworld.com/comment.php?mode=view&cid=128969

If there are any local volumes other than the boot volume mounted when this script is run, it will try to unmount them all. If no available local volumes other than the boot volume are mounted when the script is run, it will try to mount the available volumes (in other words, it will attempt to mount any local volumes that have been unmounted but remain connected). The upshot is that I can use this to toggle the mount status for all local volumes (those which can be safely unmounted, of course). I use it with a keyboard shortcut configured in the manner described in the hint to which the comment you're reading is attached. IMO, the script included in the other comment is arguably more valuable than the hint I submitted today.

What's the benefit? For instance, if I want to run an installer that I know will take a long time to examine all volumes, this eliminates a lot of wasted time.

Edited on May 03, '12 08:29:48AM by llee



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: llee on May 07, '12 11:56:46AM

Some disk names were too long to be included, so I worked on this some more. It's not the most elegant, because it may execute some redundant commands, and may not be optimized as much as it could be, but local disk lists are usually finite enough that considerations such as those don't have to take top priority.

For clarification, I should probably state clearly what this does and what it might be good for. It toggles the mount status of all local volumes. Initially, it tries to unmount all local volumes except for your boot volume. If it finds no local volumes except for your boot volume mounted, it tries to mount them all. One practical use for it might be if you were busy working, then discovered that you needed to install something but you knew the installer would try to spend time examining all your local disks. With this script, you could unmount every local volume but your boot volume, perform the installation, then quickly mount all your available local volumes again.

-----
set alldisks to paragraphs of (do shell script "df -hlg | awk -F/ '/disk*/ {print $5}'")
try
set item 1 of alldisks to ((characters 1 thru -2 of (path to startup disk as string)) as text)
on error
set alldisks to {((characters 1 thru -2 of (path to startup disk as string)) as text)}
end try

set dur to {}
repeat with m in alldisks
considering case
set dur to dur & m
end considering
end repeat

set devnames to paragraphs of (do shell script "df -k | awk -F/ '/disk*/ {print $3}'")
set t to {}
repeat with s in devnames
set t to t & (word 1 of s)
end repeat

set the keylist to dur
set the foundDisks to t
set answer_list to {}

repeat with the_answer in keylist
set theIndex to my CollectUniqueItemIndex(keylist, (the_answer as string))
set theValue to item theIndex of foundDisks
set answer_list to answer_list & (the_answer as string)
end repeat

set active_list to {}
repeat with tish from 1 to count of answer_list
--set recordnum to tish
set this_key to item tish of answer_list
set this_value to item tish of foundDisks
--set newrec to {a:1}
set this_rec to {recordnum:tish, diskname:this_key, devname:this_value} as record
set this_rec to {diskname:this_key, devname:this_value} as record
set the end of active_list to this_rec
end repeat

set not_boot_disks to {}
set not_boot_devs to {}
repeat with ant in active_list
if diskname of ant is not in {((characters 1 thru -2 of (path to startup disk as string)) as text)} then
set not_boot_disks to not_boot_disks & (diskname of ant)
set not_boot_devs to not_boot_devs & (devname of ant)
end if
end repeat

if (count of not_boot_disks) > 0 then
repeat with b in not_boot_disks
set theIndex to my CollectUniqueItemIndex(not_boot_disks, (b as string))
set theValue to item theIndex of not_boot_devs
try
do shell script "diskutil unmount /dev/" & theValue
on error the error_message number the error_number
display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
end try
end repeat
else
--this tries to mount all available disks and isn't particular about what kind or whether already mounted
set actiondisks to {}
set allvols to paragraphs of (do shell script "diskutil list -plist | grep -o 'disk[0-9][a-z][0-9]*'")
repeat with i in allvols
if i is not in actiondisks then
set actiondisks to actiondisks & i
end if
end repeat
repeat with myitem in actiondisks
try
do shell script "diskutil mountDisk /dev/" & myitem
end try
end repeat
end if

on CollectUniqueItemIndex(theList, theItem) -- the Item can be string, number, constant, app object or list
local aListMember
repeat with i from 1 to (count theList)
set aListMember to item i of theList
if aListMember = theItem then
set theIndex to i
exit repeat
end if
end repeat
return theIndex
end CollectUniqueItemIndex
-----

Edited on May 07, '12 12:14:14PM by llee



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: llee on May 10, '12 10:32:19AM

And here's the condensed version:

-----

set alldisks to paragraphs of (do shell script "df -hlg | awk -F/ '/disk*/ {print $5}'")
set nonbootnumber to (count of alldisks)

try
set all_non_boot_disks to items 2 thru nonbootnumber of alldisks
on error
set all_non_boot_disks to {}
end try
if (count of all_non_boot_disks) > 0 then
try
activate
repeat with the_Item in all_non_boot_disks
set the_ID to (do shell script "df -hlg | grep -m 1" & space & quoted form of the_Item & space & "| grep -o 'disk[0-9][a-z][0-9]*'")
try
do shell script "diskutil unmount /dev/" & the_ID
on error the error_message number the error_number
display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
end try
end repeat
on error the error_message number the error_number
if the error_number is -128 or the error_number is -1708 then
else
display dialog "There are no unmountable volumes." buttons {"OK"} default button 1
end if
end try
else
set actiondisks to {}
set allvols to paragraphs of (do shell script "diskutil list -plist | grep -o 'disk[0-9][a-z][0-9]*'")
repeat with i in allvols
if i is not in actiondisks then
set actiondisks to actiondisks & i
end if
end repeat
repeat with myitem in actiondisks
try
do shell script "diskutil mountDisk /dev/" & myitem
end try
end repeat
end if
-----



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: baltwo on May 03, '12 01:33:15PM

Why not just use list disks to get all mounted volumes? You might have to strip out "home", but easier than dealing with devs.



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: llee on May 03, '12 05:04:57PM

I've always had trouble with "list disks" when 2 or more volumes have the same name.

Edited on May 03, '12 05:05:32PM by llee



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: baltwo on May 05, '12 06:23:36PM

On my single-user machine, no two volumes carry the same names, so it's never been an issue. Thanks for clarifying.



[ Reply to This | # ]
Does not list SMB shares
Authored by: germ on May 03, '12 07:49:59PM

That would be what I need most...



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: Geobunny on May 04, '12 01:57:43AM

Just out of interest, what's the use-case for this? I can't say I've ever had a problem selecting disks to eject. For those who do, obviously this is a useful hint, but I'm not sure where I could put it to use?



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: JimAkin on May 04, '12 08:06:22AM

I can't speak for the original poster, but since OS X's default behavior has forsaken disk icons on the Desktop, and relegated mounted Volumes to the (often-hidden) bottom tier of the Finder-window Sidebar, I've had some minor issues managing mounted volumes.

More than once I've unintentionally left disk images mounted for days after installing applications, and I've found it a bit of a nuisance to open a Finder window to unmount external drives. None of this is major hardship or productivity killer (and yes, I know I can restore the icons to the Desktop if I choose), but the ability to check for and remove mounted volumes with a single keyboard shortcut is a welcome convenience.

Cheers,

Jim Akin

---
Jim



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: llee on May 04, '12 12:35:50PM

Or if you have a laptop with a full desktop that you don't have time to sort, and you just want out of there! (As a matter of fact, the script in my comment might work better for you in this case.)



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: emendelson on May 04, '12 06:39:33AM

A very nice script! One request: is it possible to filter out the startup disk from the list, since that can't be dismounted? I've tried to do this by myself, but haven't succeeded in making it work. If only the startup disk is mounted, the script could display a message and close.



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: llee on May 04, '12 09:04:49AM

Didn't test this thoroughly, but you're welcome to try it. Thanks.

----
set alldisks to paragraphs of (do shell script "df -hlg | awk -F/ '/disk*/ {print $5}'")
try
set item 1 of alldisks to ((characters 1 thru -2 of (path to startup disk as string)) as text)
on error
set alldisks to {((characters 1 thru -2 of (path to startup disk as string)) as text)}
end try

set dur to {}
repeat with m in alldisks
considering case
set dur to dur & m
end considering
end repeat

set devnames to paragraphs of (do shell script "df -k | awk -F/ '/disk*/ {print $3}'")
set t to {}
repeat with s in devnames
set t to t & (word 1 of s)
end repeat

set the keylist to dur
set the foundDisks to t
set answer_list to {}

repeat with the_answer in keylist
set theIndex to my CollectUniqueItemIndex(keylist, (the_answer as string))
set theValue to item theIndex of foundDisks
activate
--set answer_list to answer_list & return & ((the_answer & ":" & space & theValue) as string)
--set answer_list to answer_list & ((the_answer & ":" & space & theValue) as string)


set answer_list to answer_list & (the_answer as string)
end repeat

set active_list to {}
repeat with tish from 1 to count of answer_list
--set recordnum to tish

set this_key to item tish of answer_list
set this_value to item tish of foundDisks
--set newrec to {a:1}
set this_rec to {recordnum:tish, diskname:this_key, devname:this_value} as record
set this_rec to {diskname:this_key, devname:this_value} as record

set the end of active_list to this_rec
end repeat

set not_boot_disks to {}
set not_boot_devs to {}
repeat with ant in active_list
if diskname of ant is not in {((characters 1 thru -2 of (path to startup disk as string)) as text)} then
set not_boot_disks to not_boot_disks & (diskname of ant)
set not_boot_devs to not_boot_devs & (devname of ant)
end if
end repeat

try
set your_selected_device_id to choose from list not_boot_disks with prompt "Please choose one or more volumes to be unmounted." with multiple selections allowed
repeat with b in your_selected_device_id
set theIndex to my CollectUniqueItemIndex(not_boot_disks, (b as string))
set theValue to item theIndex of not_boot_devs
try
do shell script "diskutil unmount /dev/" & theValue
on error the error_message number the error_number
display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
end try
end repeat
on error
display dialog "The boot volume is the only volume mounted, so it's not possible to unmount anything!" buttons {"OK"} default button 1
end try

on CollectUniqueItemIndex(theList, theItem)
local aListMember
repeat with i from 1 to (count theList)
set aListMember to item i of theList
if aListMember = theItem then
set theIndex to i
exit repeat
end if
end repeat
return theIndex
end CollectUniqueItemIndex
----



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: emendelson on May 04, '12 11:51:35AM

That revised script seems to work perfectly on my system. Thank you! It might be worth replacing the original post with this one, I think.

Thanks again!



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: llee on May 04, '12 07:03:51PM

Canceling the disk list dialog results in getting the "no ejectable" warning. To fix that, try changing

display dialog "The boot volume is the only volume mounted, so it's not possible to unmount anything!" buttons {"OK"} default button 1

to

if the error_number is -128 or the error_number is -1708 then
else
display dialog "Error: " & the error_number & ". " & "The boot volume is the only volume mounted, so it's not possible to unmount anything!" buttons {"OK"} default button 1
end if



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: emendelson on May 06, '12 07:16:46AM

Thank you for this fix. In order to avoid an error message, I had to make a change in the "on error" block that contains the new text: I changed

on error

to:

on error number the error_number

and then all worked well.

Thanks again!



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: llee on May 07, '12 12:18:14PM

And thank you!

For good measure, I'll include the complete version with all the incremental fixes. Thanks again.

------
set alldisks to paragraphs of (do shell script "df -hlg | awk -F/ '/disk*/ {print $5}'")
try
set item 1 of alldisks to ((characters 1 thru -2 of (path to startup disk as string)) as text)
on error
set alldisks to {((characters 1 thru -2 of (path to startup disk as string)) as text)}
end try

set dur to {}
repeat with m in alldisks
considering case
set dur to dur & m
end considering
end repeat

set devnames to paragraphs of (do shell script "df -k | awk -F/ '/disk*/ {print $3}'")
set t to {}
repeat with s in devnames
set t to t & (word 1 of s)
end repeat

set the keylist to dur
set the foundDisks to t
set answer_list to {}

repeat with the_answer in keylist
set theIndex to my CollectUniqueItemIndex(keylist, (the_answer as string))
set theValue to item theIndex of foundDisks
activate
--set answer_list to answer_list & return & ((the_answer & ":" & space & theValue) as string)
--set answer_list to answer_list & ((the_answer & ":" & space & theValue) as string)


set answer_list to answer_list & (the_answer as string)
end repeat

set active_list to {}
repeat with tish from 1 to count of answer_list
--set recordnum to tish

set this_key to item tish of answer_list
set this_value to item tish of foundDisks
--set newrec to {a:1}
set this_rec to {recordnum:tish, diskname:this_key, devname:this_value} as record
set this_rec to {diskname:this_key, devname:this_value} as record

set the end of active_list to this_rec
end repeat

set not_boot_disks to {}
set not_boot_devs to {}
repeat with ant in active_list
if diskname of ant is not in {((characters 1 thru -2 of (path to startup disk as string)) as text)} then
set not_boot_disks to not_boot_disks & (diskname of ant)
set not_boot_devs to not_boot_devs & (devname of ant)
end if
end repeat

try
set your_selected_device_id to choose from list not_boot_disks with prompt "Please choose one or more volumes to be unmounted." with multiple selections allowed
repeat with b in your_selected_device_id
set theIndex to my CollectUniqueItemIndex(not_boot_disks, (b as string))
set theValue to item theIndex of not_boot_devs
try
do shell script "diskutil unmount /dev/" & theValue
on error the error_message number the error_number
display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
end try
end repeat
on error the error_message number the error_number
if the error_number is -128 or the error_number is -1708 then
else
display dialog "Error: " & the error_number & ". " & "The boot volume is the only volume mounted, so it's not possible to unmount anything!" buttons {"OK"} default button 1
end if
end try

on CollectUniqueItemIndex(theList, theItem)
local aListMember
repeat with i from 1 to (count theList)
set aListMember to item i of theList
if aListMember = theItem then
set theIndex to i
exit repeat
end if
end repeat
return theIndex
end CollectUniqueItemIndex
------



[ Reply to This | # ]
This script is flawed!
Authored by: vczilla on May 07, '12 03:48:54PM

I'm sorry to have to point this out but this script does not work.

The main problem is this:

It builds two list, one of all local mount points and the other of their corresponding device names. Or at least that's the theory but in practice the first list is built using 'df -l' which indeed list the free space of all local volumes whereas the other one is built with 'df -k' which simply lists the free space of *all* mounted volumes ( the parameter '-k' here tells df to use 1024k blocks, it is useless for our purpose ).

So the two lists are out of sync and the wrong disk ends up being unmounted.

Anyway for the tl;dr crowd here is a corrected version (I hope ! I would look stupid otherwise ;-) )

set my_devs to {}
set my_disks to {}

set startup_disk to (characters 1 thru -2 of (path to startup disk as text)) as text

repeat with p in paragraphs of (do shell script "df -l|tail -n +2")
	try
		set my_dev to (do shell script "echo " & p & "|awk '{print $1}'")
		set my_disk to (do shell script "echo " & p & "|awk -F / '{print $5}'")
		if (my_disk is not "") then
			set the end of my_disks to my_disk
			set the end of my_devs to my_dev
		end if
	end try
end repeat

set your_selected_device_ids to choose from list my_disks with prompt "Please choose one or more volumes to be unmounted." with multiple selections allowed

repeat with my_res in your_selected_device_ids
	set my_id to get_index_from_element(my_disks, my_res as text)
	set my_dev to item my_id of my_devs
	try
		do shell script "diskutil unmount " & my_dev
	end try
end repeat

on get_index_from_element(my_list, my_item)
	local item_to_test
	
	repeat with i from 1 to (count my_list)
		set item_to_test to item i of my_list
		if item_to_test = my_item then
			return i
		end if
	end repeat
	error "Item:" & my_item & " not found " from my_list
end get_index_from_element

Please note that this was merely an exercise in correction and this script is by no way the shortest or most elegant way of doing this. For instance as someone suggested we could unmount our selected devices by name using only one list.

If I have time I'll repost a comment with this script redone in perl and parsing the output of diskutil because 'df -l' mistakenly lists a USB volume as a local volume on my machine.

Edited on May 07, '12 11:43:40PM by vczilla


[ Reply to This | # ]
This script is flawed!
Authored by: llee on May 08, '12 10:24:23PM

But "df -k | awk -F/ '/disk*/ {print $3}'" doesn't list all mounted volumes, not in Lion, anyway. The "df" command apparently always lists results in the same order, so, if the corresponding lists both reflect members which are appropriately filtered, as appears to be the case for the original script, then the items are matched correctly. Also, how could a USB volume be considered anything other than a local volume? If you don't consider it local, how do you define it?

Edited on May 08, '12 10:33:44PM by llee



[ Reply to This | # ]
This script is flawed!
Authored by: vczilla on May 09, '12 12:10:12PM

Hi llee,

This is 'df -k' on my machine:

%df -k
Filesystem                  1024-blocks      Used Available Capacity  Mounted on
/dev/disk0s2                   79203656  37059420  41888236    47%    /
devfs                               213       213         0   100%    /dev
map -hosts                            0         0         0   100%    /net
map auto_home                         0         0         0   100%    /home
/dev/disk2s2                  365784156 332133392  33650764    91%    /Volumes/LionHD
/dev/disk1s1                   66559996  65618364    941632    99%    /Volumes/NtfsData
/dev/disk1s2                   36141052  35825216    315836   100%    /Volumes/Stuff
/dev/disk1s3                   53588152  48312924   5275228    91%    /Volumes/Spare
/dev/disk3s1                  256702603 251655315   5047288    99%    /Volumes/LX 640GB
/dev/disk3s2                  306239060 303196948   3042112   100%    /Volumes/MacExt
//mono@mono-ubuntu/DATA        90905756  88700324   2205432    98%    /Volumes/DATA
/dev/disk3s3                   35929372  34222204   1707168    96%    /Volumes/SmallSave
//mono@mono-ubuntu/SHARED      30925528  28483832   2441696    93%    /Volumes/SHARED
//mono@mono-ubuntu/WINSHARE   122047484 119958196   2089288    99%    /Volumes/WINSHARE
/dev/disk4s2                     113970    113970         0   100%    /private/tmp/UpdateEngine-mount.gg0KUq6yFM
/dev/disk2s3                  365949948 333945836  32004112    92%    /Volumes/Windows 8

The three volumes with names in all caps are SMB shares mounted by the finder.

Now 'df -hlg':

%df -hlg
Filesystem   1G-blocks Used Available Capacity  Mounted on
/dev/disk0s2        75   35        39    47%    /
/dev/disk2s2       348  316        32    91%    /Volumes/LionHD
/dev/disk1s3        51   46         5    91%    /Volumes/Spare
/dev/disk3s2       292  289         2   100%    /Volumes/MacExt
/dev/disk3s3        34   32         1    96%    /Volumes/SmallSave
/dev/disk4s2         0    0         0   100%    /private/tmp/UpdateEngine-mount.gg0KUq6yFM
And for good measure the output of 'mount':
%mount
/dev/disk0s2 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)
/dev/disk2s2 on /Volumes/LionHD (hfs, local, journaled)
/dev/disk1s1 on /Volumes/NtfsData (ntfs-3g, local, synchronous)
/dev/disk1s2 on /Volumes/Stuff (ntfs-3g, local, synchronous)
/dev/disk1s3 on /Volumes/Spare (hfs, local, journaled)
/dev/disk3s1 on /Volumes/LX 640GB (ntfs-3g	, local, nodev, nosuid, synchronous)
/dev/disk3s2 on /Volumes/MacExt (hfs, local, nodev, nosuid, journaled, noowners)
//mono@mono-ubuntu/DATA on /Volumes/DATA (smbfs, nodev, nosuid, mounted by mono)
/dev/disk3s3 on /Volumes/SmallSave (hfs, local, nodev, nosuid, journaled, noowners)
//mono@mono-ubuntu/SHARED on /Volumes/SHARED (smbfs, nodev, nosuid, mounted by mono)
//mono@mono-ubuntu/WINSHARE on /Volumes/WINSHARE (smbfs, nodev, nosuid, mounted by mono)
/dev/disk4s2 on /private/tmp/UpdateEngine-mount.gg0KUq6yFM (hfs, local, nodev, nosuid, read-only, noowners, nobrowse)
/dev/disk2s3 on /Volumes/Windows 8 (ntfs-3g, local, synchronous)

Hence the problem I mentioned.

You have two lists of a different size so when the script is using the position of an item in the first list to index an item in the second list the wrong item is picked up from the list and the wrong drive ends up being unmounted.

Just try both ( your version and mine ) and you'll see.

As for the second point you mentioned, you are totally right, USB drives are local disks and 'df -l' is of course completely justified in listing them. I was somehow thinking about 'internal drives' when I wrote my post.



[ Reply to This | # ]
This script is flawed!
Authored by: llee on May 09, '12 01:08:59PM

The only way that I could replicate your results, I guess, would be to try to create mountable volumes with all those disk names. But I did considerable testing on the script I submitted with quite a few different volumes mounted. The list you include first (yours is generated by "df -k") when generated by my script does not include all the volumes that yours includes because it isn't "df -k", it's "df -k | awk -F/ '/disk*/ {print $3}'", and it returns a listing for only the items appearing in your second list. My observation is that because the order of the listed items doesn't change between the filtering of the constructs based on "df -k" and "df -hlg", the script that filters out ineligible members still draws the correct association of items in the two lists. Can you store the output of the two initial commands from my script ("df -k | awk -F/ '/disk*/ {print $3}'", and "df -hlg | awk -F/ '/disk*/ {print $5}'") on your system so they can be compared line for line with the output you already included for "df -hlg"?

I know you already developed your own version which I find also appears to work for me, but it occurred to me that a refinement of the grep construct might provide both lists from "df -hlg" instead of one from "df -hlg" and the other from "df -k", so making that assumption, please see if the following change allows my script work for you.

In the original script, change

"df -k | awk -F/ '/disk*/ {print $3}'"

to

"df -hlg | grep -o 'disk[0-9][a-z][0-9]*'"

Based on that, I may be able to work out a version which doesn't involve creating the hash table (matching items of two lists).

Edited on May 09, '12 01:30:41PM by llee



[ Reply to This | # ]
This script is flawed!
Authored by: llee on May 09, '12 08:22:33PM

Hmm, well, could it be as short and sweet as this?

-----
set alldisks to paragraphs of (do shell script "df -hlg | awk -F/ '/disk*/ {print $5}'")
set nonbootnumber to (count of alldisks)
try
set alldisks to items 2 thru nonbootnumber of alldisks
activate
set your_selected_device_id to choose from list alldisks with prompt "Please choose one or more volumes to be unmounted." with multiple selections allowed
repeat with the_Item in your_selected_device_id
set the_ID to (do shell script "df -hlg | grep -m 1" & space & quoted form of the_Item & space & "| grep -o 'disk[0-9][a-z][0-9]*'")
try
do shell script "diskutil unmount /dev/" & the_ID
on error the error_message number the error_number
display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
end try
end repeat
on error the error_message number the error_number
if the error_number is -128 or the error_number is -1708 then
else
display dialog "There are no unmountable volumes." buttons {"OK"} default button 1
end if
end try
-----

Edited on May 09, '12 08:55:12PM by llee



[ Reply to This | # ]
I like it (shorter and simpler)
Authored by: vczilla on May 10, '12 09:32:23AM

I tried your shorter version and indeed it works here too. I think the key to this story was to have just one list, the one generated by 'df -l'.

Since you asked me (and I know that doesn't really matter anymore),
here is the output of 'df -k | awk -F/ '/disk*/ {print $3}' on my machine:

% df -hlg | awk -F/ '/disk*/ {print $5}'

LionHD
Spare
MacExt
SmallSave

and 'df -k | awk -F/ '/disk*/ {print $3}':

 df -k | awk -F/ '/disk*/ {print $3}'
disk0s2                   79203656  51490116  27457540    66%    
disk2s2                  365784156 332114676  33669480    91%    
disk1s1                   66559996  65618364    941632    99%    
disk1s2                   36141052  35825216    315836   100%    
disk1s3                   53588152  48312940   5275212    91%    
disk3s1                  256702603 251655316   5047286    99%    
disk3s2                  306239060 303196908   3042152   100%    
disk3s3                   35929372  34222232   1707140    96%   

That's why it didn't work here.

As a side note, there's a slight typo in the awk script regex, which should be /disk.*/ and not /disk*/ (luckily it doesn't change anything for the intended purpose).

I'm glad you didn't take it the wrong way and that you came up with a really short solution, and I hope I didn't came off as being too pedantic. ;-)



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: morespace54 on May 09, '12 10:15:09AM

Great script! Thanks. Unfortunately, it doesn't seems to work on my (stubborn) USB HD, which I still have to "force eject" from the Finder (or worst, turn it off completely)...



[ Reply to This | # ]
AppleScript for selecting local volumes to unmount
Authored by: llee on May 09, '12 01:14:59PM

You may have to find and quit what's using the disk before it will unmount. One way to do that might be to search for the path to your volume in the output of the terminal command "lsof".



[ Reply to This | # ]