Skip to content

Instantly share code, notes, and snippets.

@pascalpp
Last active August 6, 2023 17:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pascalpp/56d0f8d70a7771eb1204d544459ffd88 to your computer and use it in GitHub Desktop.
Save pascalpp/56d0f8d70a7771eb1204d544459ffd88 to your computer and use it in GitHub Desktop.
ejectdisks
#!/bin/bash
#
# ejectdisks
# script to unmount all external drives on a Mac
# assumes your external volumes are all 'APFS Volume' or 'Apple_HFS'
# try `diskutil list external` to see your volumes
#
# Installation
# copy this file to /usr/local/bin or somewhere in your path and make it executable
# chmod +x path/to/ejectdisks
#
# relies on timeout (part of coreutils) and terminal-notifier
# brew install coreutils terminal-notifier
#
# Usage:
#
# unmount all external disks and stop time machine
# ejectdisks
#
# show what would happen without actually ejecting disks or stopping time machine
# ejectdisks --dry-run
#
dryrun=$(echo $* | grep -e "\b--dry-run\b")
if [ "$dryrun" ]
then
echo "Dry run: no disks will be ejected. Time Machine will not be stopped. Example output shown below."
fi
# helper methods
function checkError {
EXITCODE=$?
if [ "$EXITCODE" -ne "0" ]; then
exit $EXITCODE
fi
}
function checkErrorAndNotify {
EXITCODE=$?
if [ "$EXITCODE" -ne "0" ]; then
echo $1 $2
terminal-notifier -title "$1" -message "$2"
exit 1
fi
}
function ejectdisks {
echo "Checking for extenal disks..."
# reduces diskutil output to a series of lines like 'External HD•disk5s1'
# probably a better way to do this with sed - suggestions welcome
disks=$(timeout -v 5 diskutil list external | grep -E '(APFS Volume|Apple_HFS)' | grep -v KB | perl -pe 's/.*(APFS Volume|Apple_HFS) (.*) +\d+\.?\d* [GT]B +(.*)/\2•\3/g' | perl -pe 's/ +•/•/g')
checkErrorAndNotify "Oops!" "There was a problem reading external disks."
if [ "$disks" ]
then
echo "$disks" | while read line ; do
# split the line on • to get diskname and devicename
diskname=$(echo $line | cut -d• -f1)
devicename=$(echo $line | cut -d• -f2)
echo "Ejecting $diskname..."
if ! [ "$dryrun" ]
then
diskutil eject /dev/$devicename
fi
checkError
done
fi
}
# execution starts here
terminal-notifier -title "Unmounting disks" -message "Please wait…"
# stop time machine
echo "Stopping Time Machine..."
if ! [ "$dryrun" ]
then
timeout -v 30 tmutil stopbackup
fi
checkErrorAndNotify "Oops!" "There was a problem stopping time machine."
ejectdisks
checkErrorAndNotify "Oops!" "There was a problem ejecting some disks."
echo "All disks unmounted."
terminal-notifier -title "All disks unmounted" -message "Get out of here." -sound "Glass"
# open /Volumes # uncomment to open /Volumes in Finder after ejecting disks
if [ "$dryrun" ]
then
echo "Dry run complete."
fi
@pascalpp
Copy link
Author

pascalpp commented Aug 6, 2023

Companion to mountdisks

Example output:

❯ ejectdisks
Stopping time machine...
Checking for extenal disks...
Ejecting Wrangler...
Disk /dev/disk5s2 ejected
Ejecting Tonka...
Disk /dev/disk7s1 ejected
Ejecting Spree...
Disk /dev/disk8s2 ejected
Ejecting Frog Ville...
Disk /dev/disk10s1 ejected
All disks unmounted.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment