Equivalent of alias for a symbolic link?

Shell aliases have the feature that you can do (some) name-completion on them (usually bound to tab). Alternatively, you can use the CDPATH feature, which "recently" (within the past 5-6 years) has been improved to support name-completion. If that works for you, it has the advantage that the what you type is the actual name of the directory rather than a mnemonic for it.

According to the bash manual

CDPATH
A colon-separated list of directories used as a search path for the cd builtin command.

Further reading:

  • Bash Reference Manual
  • Some Bash tricks: CDPATH and ~/.inputrc
  • Use CDPATH to access frequent directories in bash
  • bash: Is there a way to use tab completion through out CDPATH?
  • CDPATH Bash completion in OSX

For the directories you frequent often, but don't change daily, another option is just to have several alias commands in your .bashrc file:

alias cdo="cd /u01/app/oracle"
alias cdw="cd /var/www/html" 

A friend has about 50 of those; I have a handful; quick and easy. Just

cdo

to change directory to /u01/app/oracle


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. :)