Can I hook into the cd command?

With ksh or bash (or zsh):

cd() {
  builtin cd "$@" || return
  [ "$OLDPWD" = "$PWD" ] || case $PWD in
      (*/public_html) echo do something
    esac
}

With zsh:

chpwd()
  case $PWD in
    (*/public_html) echo do something
  esac

(chpwd is a hook function that is called whenever the current working directory changes (by way of cd, pushd, popd...)).


You could add this function to your .bashrc or other startup file (depending on your shell).

cd() {      
   if [ "$1" = "public_html" ]; then
      echo "current dir is my dir"
   fi
   builtin cd "$1"
}

Wrapping cd, an existing command, is not recommended.

A more universal solution would be defining a custom chpwd hook in Bash. (According to tags of this question, I assume you're using Bash)

There's not a complete hook system designed in Bash when compared with other modern shells. PROMPT_COMMAND variable is used as a hook function, 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

A trick is provided 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 implementaion in Bash and the chpwd in ZSH is, PROMPT_COMMAND is not supported in a non-interactive Bash shell.

Usage

_public_html_action() {
  if [[ $PWD == */public_html ]]; then
    # actions
  fi
}

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

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

For anyone want an answer for ZSH. Use chpwd hook in ZSH. Don't define chpwd() function directly. More detail here.