• Skip to primary navigation
  • Skip to main content
Sal Ferrarello
  • About Sal Ferrarello
  • Speaking
  • Connect
    Mastodon GitHub Twitter (inactive)
You are here: Home / Solution / zsh alias with fallback

zsh alias with fallback

Last updated on August 12, 2021 by Sal Ferrarello

In my zsh configuration I define a number of aliases. One particular zsh alias maps gl to my custom Git alias git lg (see Improve Git Log for details). Since my zsh configuration is portable, I want to define a fallback if my custom Git alias does not exist on the machine.

Short Answer

This is the code I added to my .zshrc

function gl() {
  git lg "$@" 2>/dev/null || \
  [ $? -eq 141 ] || \
  git log --oneline --graph "$@"
}

Note: This could be written as one long command however I’m using \ to break it up over multiple lines for readability. The following is equivalent

function gl() {
  git lg "$@" 2>/dev/null || [ $? -eq 141 ] || git log --oneline --graph "$@"
}

Why a Function?

Initially, I tried an alias (e.g. alias gl="git lg || git log --oneline --graph"), which worked great until I realized it did not support passing in arguments.

e.g. gl develop would ignore the “develop” part of the command and run just git lg (instead of git lg develop)

To fix this, I needed to provide the arguments from the command, which are available in the environment variable $@. Unfortunately, we can not use a variable in an alias so we’re using a function instead.

Why 2>/dev/null ?

When you run a command from the command line, two different streams of data are output to the screen (stdout and stderr). The stdout is the output of the command, while stderr is any error messages.

If you try to run git lg and the Git alias does not exist, the following is output on the screen through the stderr stream.

git: 'lg' is not a git command. See 'git --help'.

The most similar command is
        log

If we do not include 2>/dev/null with out git lg command, when it fails we get the above output before the output of the fallback (git log --oneline --graph).

By adding 2>/dev/null, we send the stderr to /dev/null, which makes it disappear (preventing the above error message from displaying when git lg fails).

Why || ?

The || is a logical OR, which says if the first command fails then run the next command. If the first command succeeds, then do not run the second.

An Example

You can try running the following from the command line.

echo "one" || echo "two"

This will display one (the second command does not run because the first was successful)

Another Example

You can try running the following from the command line.

notacommand || echo "two"

This will display an error message and then because the first command failed, it will display two

You can suppress the error message with 2>/dev/null, now this will only display “two” (the fallback)

notacommand 2>/dev/null || echo "two"

Remember 2/dev/null only suppresses the error message, so if we do the following we still get just one in the output

echo "one" 2>/dev/null || echo "two"

What is success?

How does the machine know the command was successful? Whenever a command is run an exit code is returned, if the code is zero (0), the command is considered successfully run. The exit code for the last command is stored in the environment variable $?

Example of Exit Code

Running the command echo $? will output the last exit code. e.g.

If you run the command ls and then run

echo $?

The output will be 0

If you run the command notacommand (you will see an error message on the screen) and if you then run

echo $?

The output will be 127 (a non-zero exit code, indicating an unsuccessful command).

Why [ $? -eq 141 ]

As mentioned above, a command is considered successful when the exit code is zero (0), however git log sometimes returns an exit code of 141 when it runs “successfully” (see git log exit code 141? for more details).

Therefore we add this check to see if the exit code ($?) is equal (-eq) to 141. If it is equal, this check returns an exit code of its own of 0, which prevents running the fallback command.

Result

The result of this learning journey is this function definition in my zsh configuration.

function gl() {
  git lg "$@" 2>/dev/null || \
  [ $? -eq 141 ] || \
  git log --oneline --graph "$@"
}
Sal Ferrarello
Sal Ferrarello (@salcode)
Sal is a PHP developer with a focus on the WordPress platform. He is a conference speaker with a background including Piano Player, Radio DJ, Magician/Juggler, Beach Photographer, and High School Math Teacher. Sal can be found professionally at WebDevStudios, where he works as a senior backend engineer.

Share this post:

Share on TwitterShare on FacebookShare on LinkedInShare on EmailShare on Reddit
Warning! This is a draft, not a finalized post. See full draft disclosure.

Filed Under: Dev Tips, Draft, Programming, Solution Tagged With: zsh

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Copyright © 2023 · Bootstrap4 Genesis on Genesis Framework · WordPress · Log in