Harness the Combinatoric Power of Command-Line Tools and Utilities

../Tutorials

How to Use macOS Notifications with Command-line Programs

Bash macOS zsh scripts

Published January 8, 2020 and last verified on March 10, 2024

When you execute some long-running commands in your console, you probably want some kind of notification to let you know when things are done. The longer a program takes to run, the more tempted you might be to switch to another task and work on that, only to find out that your program finished hours ago.

Using a combination of shell scripting and AppleScript, you can create a function that pops up notifications on your Mac when a command finishes.

You can execute multiple commands by separating them with semicolons. For example, you can create a directory and switch to it in a single command like this:

mkdir mydirectory; cd mydirectory

The first command executes, and the second command executes once the first has finished.

To make a notification on macOS, use this command to execute an AppleScript code snippet from your terminal:

osascript -e 'display notification "The command finished" with title "Success"'

You’ll see the message appear in your notification section.

Typing that out all the time isn’t a great approach, so take advantage of shell functions to do the work.

You define shell functions in the startup script associated with your shell. macOS versions prior to Catalina use the Bash shell, while new accounts on macOS Catalina use ZSH by default.

Use the following command to determine your shell:

echo $0

If you’re using the Bash shell, open the file ~/.bash_profile in your editor:

nano ~/.bash_profile

If you’re using ZSH, open the file ~/.zshrc:

nano ~/.zshrc

Add the following function called notifyMe:

notifyMe() {
  osascript -e 'display notification "The command finished" with title "Success"'
}

Exit the editor and the file with CTRL+X, followed by y.

Close and open your Terminal window again to apply the changes, or use the source command to re-read your configuration file.

Then test the notification:

sleep 5; notifyMe

After five seconds, you’ll see the notification.

You can take this even further by looking at the result code from the previous command. A well-behaved shell program will return a status code of 0 when it completes successfully, and a non-zero number if there was an error. You can read the error code with $? and evaluate it.

You can modify the notifyMe function to evaluate the error code and display a success or failure message like this:

notifyMe() {
  if [ $? -eq 0 ]; then
    osascript -e 'display notification "The command worked" with title "Success"'
  else
    osascript -e 'display notification "The command failed" with title "Failed"'
  fi
}

Test it out by using the ls command with invalid options:

ls -zzzzz; notifyMe

This time you’ll see a failure message.

Unfortunately, some commands don’t follow this approach. The find command, for example, still returns a 0 exit code when it fails. So while this error checking approach is useful most of the time, there are places where it might not tell you the truth.

In this brief article, you triggered a macOS notification message from your Terminal, created a shell function so you can use it with other programs, and explored checking the result of the previous program to control which message to display.

You can also use Apple’s say command to get an audible message instead of a notification. That’s something for you to explore on your own.