With any POSIX implementation of cd
, you can use the -P
option to do this.
$ help cd
...
-P use the physical directory structure without following symbolic links
...
You can see it in action here:
$ mkdir foo
$ ln -s foo bar
$ cd -P bar
$ pwd
/tmp/tmp.WkupF2Ucuh/foo
If you want this to be the default behaviour, you can either create an alias for cd
, like so:
alias cd='cd -P'
...or use set -o physical
. For tcsh, the equivalent command is set symlinks=chase
.
You could use tab completion. By default on many Linux distributions, bash is set up so that when you hit the [TAB] key, you're given a list of possible matches, or if there's just one match, it's all filled out. For cd, this is normally a list of subdirectories of the current working directory. You could overwrite that, but I suggest instead making an alias, like jd
for "jump directory":
alias jd=cd
and then, defining the "bookmarks" you want as completions for jd. Look at the bash man page for a lot more options (including auto-generating the results on the fly from a command or function), but the easiest way is just a list of words, with -W
:
complete -W "/srv/www ~/tmp ~/work" jd
Now, type jd
and hit [TAB], and you'll see your "bookmarks". Type any ambiguous part, and then hit [TAB] to complete. (In the above, the ~
s expand to my home directory, so the first [TAB] gives me a /
, and if I hit w
and [TAB] again, /srv/www
is filled out.)
Of course, put this in ~/.bash_profile
to make it persist.
Or, we can take this to the next level. Make a directory ~/.shortcuts
— starting with a dot, it'll be hidden and not muss up your nice clean home directory — and fill that with symlinks to your desired directories. Then, put this in your ~/.bash_profile:
_list_shortcuts()
{
COMPREPLY=($( compgen -W "$( ls ~/.shortcuts )" -- ${COMP_WORDS[COMP_CWORD]} ))
}
jd()
{
cd -P ~/.shortcuts/$1
}
complete -F _list_shortcuts jd
This defines a slightly more complicated completion in the fuction _list_shortcuts
to build the list of names, and makes jd
be a function rather than a simple alias, since we want it to act differently from just cd
. The -P
flag to cd
makes it resolve the symlinks, so everything becomes transparent magic. Your shortcut names don't even have to match the targets.
So:
$ ls -l ~/.shortcuts/
total 0
lrwxrwxrwx. 1 mattdm mattdm 16 Dec 17 19:44 tmp -> /home/mattdm/tmp
lrwxrwxrwx. 1 mattdm mattdm 17 Dec 17 19:44 WORK -> /home/mattdm/work
lrwxrwxrwx. 1 mattdm mattdm 8 Dec 17 19:44 www -> /srv/www
$ jd tmp
$ pwd
/home/mattdm/tmp
$ jd WORK
/home/mattdm/work
And, for an extra dose of fancy, make jd
list all of your shortcuts when executed without any parameters:
jd()
{
if [[ -z "$1" ]]; then
(cd ~/.shortcuts; stat -c '%N' *)
else
cd -P ~/.shortcuts/$1
fi
}
Note: I use compgen -W $( cmd )
instead of compgen -C 'cmd'
because the latter never works for me and I don't understand why. That might be a new question of my own. :)
Best Answer
Depending on how your
pwd
command is configured, it may default to showing the logical working directory (output bypwd -L
) which would show the symlink location, or the physical working directory (output bypwd -P
) which ignores the symlink and shows the "real" directory.For complete information you can do
Inside a symlink, this will return