The problem
When using the tmux terminal multiplexer, it will open new windows with the present working directory $PWD
set to whatever it was when you created the tmux session.
However, if $PWD
includes a symlink referring to some other physical path, tmux will know only about the physical path, and so $PWD
in new tmux windows will refer to the physical rather than logical path.
This is not a tmux bug—conceptually, there is seemingly no way for tmux to achieve the desired behaviour, since it only ever knows about the physical directory.
For instance, my $HOME
is set to /home/q/qmorris/jawinter
, which resolves to /gpfs/fs1/home/q/qmorris/jawinter
, since /home
is symlinked to /gpfs/fs1/home
.
Unfortunately, if you launch tmux in a subdirectory relative to $HOME
, it can see only the physical path.
This results in a horrifically ugly $PS1
prompt in Bash, since tmux will instruct Bash to use as the working directory whatever path tmux has resolved.
Our goal is to have Bash use the logical working directory, which allows it to strip the leading portion of the directory that corresponds to the home directory when generating the $PS1
prompt.
The solution
While there exist a number of possible solutions that force tmux to use the logical working directory, all seemed overly complex or fragile.
I came up with a different method that requires only dropping the following snippet in your ~/.bashrc
.
function correct_home {
[[ -n "$TMUX" ]] || return
_BASEHOME=$(realpath $HOME)
[[ $PWD =~ ^$_BASEHOME ]] || return
cd $(echo $PWD | sed 's|^'$_BASEHOME'|'$HOME'|')
}
correct_home
This function will be executed only once when the shell is launched by a new window created through tmux.
As tmux sets the $TMUX
environment variable, we can detect when this code is run outside tmux and abort immediately.
If execution proceeds, the code simply detects if the shell’s $PWD
is under the physical home directory, and replaces this portion with the logical path that Bash knows about through $HOME
.