gnome-terminal: how to preserve symlinks of working directory when opening new tab?

6

3

If I'm using gnome-terminal in a working directory whose path includes symlinks and I open a new tab, the symlinks will be expanded to their destinations in the working directory of the new tab.

Is there any way to preserve the symlinks when opening a new tab?

Ian Mackinnon

Posted 2010-08-31T13:08:08.367

Reputation: 3 919

I cannot reproduce the behavior you describe with Ubuntu 10.04 and all default settings for gnome-terminal and bash. The problem may be a setting in your .bashrc; try moving it temporarily out of the way to check. If the problem persists, add more information, at least the versions of gnome-terminal and bash, and a detailed list of steps to reproduce this behavior. – Gilles 'SO- stop being evil' – 2010-08-31T21:15:33.023

1I can reproduce it. By "directory that includes symlinks" he means "working directory whose path includes symlinks". Under gnome-terminal 2.30.2 and bash 4.1.5: mkdir -p foo/bar/baz; ln -s foo/bar/baz link; cd link -- then create new tab -- then pwd. It will report "foo/bar/baz" rather than "link". – Jander – 2010-12-05T21:30:41.437

@Jander, thanks, I'll edit to include your clarification. – Ian Mackinnon – 2010-12-05T22:30:11.777

Answers

4

I suspect there is no truly good answer to this. gnome-terminal finds bash's current working directory by inspecting /proc/<pid>/cwd, which has the symlinks expanded (probably for security reasons, if nothing else). I don't know of another way for one process to find another process's working directory.

As a workaround, there are some bash tricks you could try, but see the WARNING below! In .bashrc:

...
PROMPT_COMMAND='pwd >~/.bashlocal_saved_dir'
...

[ -n "$PS1" -a -f ~/.bashlocal_saved_dir ] && cd `cat ~/.bashlocal_saved_dir`
# end of .bashrc

This will do two things. First, every time bash displays the prompt, it will first write its current working directory into the file .bashlocal_saved_dir in your home directory. Second, when bash starts interactively (as opposed to running a script), it will change to the directory stored in that same file. This means that when you start a new interactive bash, it will start in the same dir as the bash that last displayed its prompt. Note that you can hit Enter to cause a bash to redisplay its prompt, thus making it the last. :)

WARNING: This is a hack, and I have only tried it up to the point that I know it works. Think bubble gum and shoestrings. It may have surprising effects, and will certainly not work as cleanly as gnome-terminal's approach. In particular, if you're running a lot of tabs at once, all doing background tasks, you may very well end up in the "wrong" directory when opening a new tab.

Jander

Posted 2010-08-31T13:08:08.367

Reputation: 824

1+1. But I think a safer solution, if one only has a few working dirs with symlinks, is check if you're in one of them, and call cd accordingly. – ShreevatsaR – 2011-11-11T07:02:45.413

7

This bug is being tracked on Ubuntu Launchpad and GNOME Bugzilla.

Since this mainly annoys me with only a few directories, I use the following simpler workaround.

Suppose you have /home/username/work as a symlink to /long/path/named/asdf. So you do cd ~/work in gnome-terminal, open a new tab, and find terminal reporting the full path. To fix this, just put the following in your .bashrc:

cd ${PWD/\/long\/path\/named\/asdf/$HOME\/work}

When gnome-terminal starts a new shell, it gets the current directory with $PWD, and if it contains /long/path/named/asdf, it replaces that string with $HOME/work, and cds to the resulting string. If $PWD does not contain the string, it is equivalent to cd $PWD, which does nothing.

ShreevatsaR

Posted 2010-08-31T13:08:08.367

Reputation: 776

0

I love @ShreevatsaR's answer. Expanding it to signal when this is happening and to make it so I can undo with a quick popd, I'm using:

for sub in \
    "${PWD/\/home\/vus\/.cache\/vus\/build/\/vrepos\/build}" \
    "${PWD/\/home\/vus\/repos/\/vrepos}"
do
  if [ "$sub" != "${PWD}" ] ; then
     echo -n "pushd "
     pushd "$sub"
     break # prevents first pushd from tripping later checks
  fi
done

An example new window (with PS1='#prompt# \[\033[01;34m\]\w\[\033[00;35m\]$(__git_ps1)\[\033[00m\]\$ '), including use of popd shows:

pushd /vrepos/build/2_dev_Ubuntu_Debug /home/vus/.cache/vus/build/2_dev_Ubuntu_Debug
#prompt# /vrepos/build/2_dev_Ubuntu_Debug$ popd
/home/vus/.cache/vus/build/2_dev_Ubuntu_Debug
#prompt# /home/vus/.cache/vus/build/2_dev_Ubuntu_Debug$ 

sage

Posted 2010-08-31T13:08:08.367

Reputation: 873

-1

Found this issue to be unresolved as of gnome-shell 3.14.4.

A workaround would be to use the bash Shell Variable SHLVL (which is incremented by 1 every time bash is started) in .bashrc, as follows

# bash login shell would be at level 1.
[[ $SHLVL -eq 2 ]] && cd

gnarendran142

Posted 2010-08-31T13:08:08.367

Reputation: 1