How can I make a function run every time cd successfully changes to another directory within sh on FreeBSD?
How can I make a function run every time cd successfully changes to another directory within sh on FreeBSD?
I'm using sh as my shell on FreeBSD but I want to be able to have a pretty prompt like the one bash gives me on Ubuntu. There are two things that the FreeBSD implementation of sh seems to lack as far as PS1 escape characters go:
The w
works but does not expand $HOME
to ~
, so this is something I have already hacked up myself
w
$HOME
~
I can use PS1 to update the prompt on the terminal, but as far as I can tell it is not possible to use the PS1 variable to update the title bar as well. ESC
and BEL
fail to set the title as one would expect if they were using bash or ksh
ESC
BEL
Here is my .shrc file
update_prompt() {
case "$PWD" in
"$HOME"*)
pretty_pwd="~${PWD#*"${HOME}"}"
;;
"/usr$HOME"*)
pretty_pwd="~${PWD#*"/usr${HOME}"}"
;;
*)
pretty_pwd="$PWD"
;;
esac
case "$TERM" in
xterm*|rxvt*)
PS1="[$USER@h $pretty_pwd]$ "
;;
*)
;;
esac
printf "33]0;[%s@$(hostname -s): %s]07" "$USER" "$pretty_pwd"
}
update_prompt
So when I fire up a terminal or log in via ssh, it gives the pretty prompt that I like. But now I need this function to run every time that cd is executed and returns an exit status of 0.
I was going to use an alias that was something like:
alias cd="cd $1 && update_prompt"
but that was before I realized that aliases do not except arguments. How might I go about doing something like this?
$
$
#
@MateuszPiotrowski Hey, thanks for reaching out. It probably wasn't fair to call the use of
toor
an edge case, as many FreeBSD users use the toor account to run a shell that is not part the the base FreeBSD. As per your suggestion, I tried removing the |toor
and escaping the $
in my code and it still yielded the same result when logging into the toor account. Might I ask to what you are referring to with the $
?– Harold Fischer
yesterday
toor
|toor
$
$
$
could be used the same way as h
in PS1
. For example setting PS1
to h $
results in $
being replaced with either #
or $
depending on if you're a root or no.– Mateusz Piotrowski
yesterday
$
h
PS1
PS1
h $
$
#
$
I am not sure if it works for the toor account :/
– Mateusz Piotrowski
yesterday
@MateuszPiotrowski After further investigation, I can confirm that you are correct. I just made the mistake of using
$
instead of $
(you must use two '' to escape when in double quotes). Very nice catch! Will update the code in a bit– Harold Fischer
yesterday
$
$
2 Answers
2
You can use a function instead of an alias:
cd() {
command cd "$@" && update_prompt
}
Just put it into ~/.shrc. You have to use command
here to let sh know that you are referring to the actual cd
builtin command instead of the function you've just defined.
command
cd
I use this trick in my cd
alias manager. Here's a link to the source code of the function: https://github.com/0mp/goat/blob/v2.5.0/libgoat.sh#L31-L57
cd
You can do it with alias+arguments if you swap the commands:
$ alias cd="echo change; cd"
$ pwd
/nas
$ cd /
change
$ pwd
/
$ cd /etc
change
$ pwd
/etc
$
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
BTW, the edge case of root and toor seems to be handled by
$
. Here's the fragment from the sh(1) manual: Superuser status.$
for normal users and#
for superusers.– Mateusz Piotrowski
Jun 30 at 8:08