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.