Skip to content

Instantly share code, notes, and snippets.

@laggardkernel
Last active November 30, 2023 09:07
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save laggardkernel/6cb4e1664574212b125fbfd115fe90a4 to your computer and use it in GitHub Desktop.
Save laggardkernel/6cb4e1664574212b125fbfd115fe90a4 to your computer and use it in GitHub Desktop.
Create chpwd Equivalent Hook in Bash #bash #hook #zsh

There's not a complete hook system designed in Bash when compared with other modern shells. PROMPT_COMMAND variable is used as a hook in Bash, which is equivalent to precmd hook in ZSH, fish_prompt in Fish. For the time being, ZSH is the only shell I've known that has a chpwd hook builtin.

PROMPT_COMMAND

If set, the value is interpreted as a command to execute before the printing of each primary prompt ($PS1).

https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Bash-Variables

chpwd Hook in Bash

To achieve this in Bash, a trick is provided here to setup a chpwd equivalent hook in Bash based on PROMPT_COMMAND.

# create a PROPMT_COMMAND equivalent to store chpwd functions
typeset -g CHPWD_COMMAND=""

_chpwd_hook() {
  shopt -s nullglob

  local f

  # run commands in CHPWD_COMMAND variable on dir change
  if [[ "$PREVPWD" != "$PWD" ]]; then
    local IFS=$';'
    for f in $CHPWD_COMMAND; do
      "$f"
    done
    unset IFS
  fi
  # refresh last working dir record
  export PREVPWD="$PWD"
}

# add `;` after _chpwd_hook if PROMPT_COMMAND is not empty
PROMPT_COMMAND="_chpwd_hook${PROMPT_COMMAND:+;$PROMPT_COMMAND}"

Since we're detecting PWD change directly, the solution works with cd, pushd, and popd.

Note: The main difference between our chpwd implementation in Bash and the chpwd in ZSH is, PROMPT_COMMAND is not supported in a non-interactive Bash shell.

Usage

# example 1: `ls` list directory once dir is changed
_ls_on_cwd_change() {
  ls
}

# append the command into CHPWD_COMMAND
CHPWD_COMMAND="${CHPWD_COMMAND:+$CHPWD_COMMAND;}_ls_on_cwd_change"

# or just use `ls` directly
CHPWD_COMMAND="${CHPWD_COMMAND:+$CHPWD_COMMAND;}ls"

Source: Create chpwd Equivalent Hook in Bash from my gist.

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