Created
March 21, 2025 03:16
-
-
Save quinncomendant/4778d829fc5e9258850c6d258beca2ac to your computer and use it in GitHub Desktop.
A bash script to raise a macOS notification or alert with no dependencies. Save this file as `notify` and then symlink it to `alert`.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# | |
# Quinn Comendant <[email protected]> | |
# 11 Jul 2020 11:18:13 | |
set -o pipefail; | |
set -o errexit; | |
set -o nounset; | |
set -o noclobber; | |
scriptname=$(basename "$0"); | |
# | |
# Functions | |
# | |
function _usage() { | |
echo "Usage: $scriptname [OPTIONS] [< STDIN] | |
Raise a macOS notification using AppleScript. | |
OPTIONS | |
-m MESSAGE The notification message (required if not using STDIN). | |
-s SUBTITLE A notification subtitle. | |
-S Play a notification sound. | |
-t TITLE A notification title. | |
"; | |
exit 1; | |
} | |
function _error() { | |
local IFS=''; | |
echo -e "$*" 1>&2 | |
exit 1; | |
} | |
function _notify() { | |
export notify_message notify_subtitle notify_title notify_sound; | |
if [[ -n $notify_sound ]]; then | |
osascript -e 'display notification (system attribute "notify_message") with title (system attribute "notify_title") subtitle (system attribute "notify_subtitle") sound name (system attribute "notify_sound")' >/dev/null & | |
# osascript -e 'tell application "Finder"' -e 'activate' -e 'display notification (system attribute "notify_message") with title (system attribute "notify_title") subtitle (system attribute "notify_subtitle") sound name (system attribute "notify_sound")' -e 'end tell' & | |
else | |
osascript -e 'display notification (system attribute "notify_message") with title (system attribute "notify_title") subtitle (system attribute "notify_subtitle")' >/dev/null & | |
# osascript -e 'tell application "Finder"' -e 'activate' -e 'display notification (system attribute "notify_message") with title (system attribute "notify_title") subtitle (system attribute "notify_subtitle")' -e 'end tell' & | |
fi | |
} | |
function _alert() { | |
if [[ -n $notify_subtitle ]]; then | |
notify_title="${notify_title} (${notify_subtitle})"; | |
fi | |
export notify_message notify_title notify_sound; | |
osascript -e 'display alert (system attribute "notify_title") message (system attribute "notify_message") as critical buttons {"OK"} default button "OK"' >/dev/null & | |
# osascript -e 'tell application "Finder"' -e 'activate' -e 'display alert (system attribute "notify_title") message (system attribute "notify_message") as critical buttons {"OK"} default button "OK"' -e 'end tell' >/dev/null & | |
if [[ -n $notify_sound ]]; then | |
sleep 1 && afplay /System/Library/Sounds/Pop.aiff &>/dev/null & | |
fi | |
} | |
function _iconv() { | |
local str; | |
read -rd '' str; | |
iconv -f UTF8 -t MACROMAN//IGNORE <<<"$str" 2>/dev/null || true; | |
} | |
# | |
# Main | |
# | |
# Look at stdin for the message (`-t 0` tests if input is not a tty, i.e., stdin exists via pipe). | |
notify_message=; | |
if [[ ! -t 0 ]]; then | |
notify_message=$(_iconv); | |
fi | |
# Display help if run without arguments. | |
[[ $# == 0 && -z $notify_message ]] && _usage 1>&2 | |
# Process command line options. | |
notify_subtitle=''; | |
notify_title='Terminal'; | |
notify_sound=''; | |
while getopts 'hm:s:St:-:' opt ; do | |
case $opt in | |
(h) _usage;; | |
(m) if [[ -n $notify_message ]]; then | |
_error "Message provided via -m and stdin; choose one and try again."; | |
fi | |
notify_message=$(_iconv <<<"$OPTARG");; | |
(t) notify_title=$(_iconv <<<"$OPTARG");; | |
(s) notify_subtitle=$(_iconv <<<"$OPTARG");; | |
(S) notify_sound='Pop';; | |
(-) case $OPTARG in | |
(help) _usage;; | |
(?) _error "Invalid option: '$OPTARG'. Run with -h for help.";; | |
esac ;; | |
(?) _error "Invalid option: '$opt'. Run with -h for help.";; | |
(*) _error "An unexpected error occurred.";; | |
esac | |
done | |
# Remove options. | |
shift $((OPTIND - 1)) | |
[[ -z $notify_message ]] && _error "No message provided. Run with -h for help."; | |
type -P osascript >/dev/null || _error "The osascript command is not available"; | |
case $scriptname in | |
(notify) _notify;; | |
(alert) _alert;; | |
esac | |
unset -v notify_message notify_subtitle notify_title notify_sound; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment