zsh provides some nice hook functions, including chpwd
for running a function after the user changes directories.
# zsh only
function greet() { echo 'hi'; }
chpwd_functions+=("greet")
cd .. # hi
pushd # hi
popd # hi
I'm trying to emulate that in bash.
Constraints:
- It must work in both interactive and non-interactive shells, which I think means that it can't rely on something like
$PROMPT_COMMAND
- It can't redefine
cd
, because I want it to work for any command that changes directories (eg,pushd
andpopd
) - It must run after the user's command, so
trap "my_function" DEBUG
doesn't work, unless I can somehow say in there, "first run the$BASH_COMMAND
we trapped, then also do this…" I see that I can avoid the automatic running of$BASH_COMMAND
ifextdebug
is enabled and the trap function returns 1, but I don't think I want to forceextdebug
, and returning1
for a successful (but modified) command seems wrong.
The last part – "run after the user's command" – is what currently has me stumped. If I can run a function after each command, I can have it check whether the directory has changed since we last checked. Eg:
function check_pwd() {
# true in a new shell (empty var) or after cd
if [ "$LAST_CHECKED_DIR" != "$PWD" ]; then
my_function
fi
LAST_CHECKED_DIR=$PWD
}
Am I on the right track, or is there a better way? How can I run a command in bash after the user changes directories?
Best Answer
There's no way that meets these constraints
It looks like there's no way to solve this problem in bash with my constraints. In general, possible solutions are:
cd
,pushd
, andpopd
, so that any command that changes directories will first run the hook function. But this can create problems because 1) the override must be careful to tab complete like the original command and return the same exit code and 2) if more than one tool takes this approach, they can't play well togethertrap 'my_function' DEBUG
so that every command will run the hook function. This is suboptimal because 1) it runs before every command, 2) it runs beforecd
, not after 3) there can only be one debug function, so if another tool uses this approach, they can't play well together$PROMPT_COMMAND
to run the hook function first. This is suboptimal because it won't work in non-interactive shells, and because if another tool defines the prompt command, they can't play well together.In short it seems like the only great solution would be if bash provided something like zshell's
chpwd_functions
hook, but it seems impossible to simulate that properly.