Bash autocomplete for different directories

Solution 1:

Reading deep into the question, you are looking for smoother ways to navigate the file tree from the command line.

Option 1: Use CDPATH

E.g., CDPATH=".:~:~/projects/ruby:~/projects/rail:~/projects/html"

Note: some people find it useful to include .. in CDPATH.

Unfortunately CDPATH doesn't (always) support autocompletion.  There are ways to extend bash to do this.  Google with terms "CDPATH" and "autocompletion".

Admittedly this is a bit clunky.  If there is a small set of parent directories you use, this isn't too bad.

You may have better success with dirs, pushd, and popd. These take some time to get the hang of. Note that pushd and popd can take a numeric parameter.

Also:
cd - returns you to the previous directory. Repeating the command toggles between the two most recent directories.
____________
A lot of documents (including man pages) show . (dot; i.e., the current directory) as a component in CDPATH.  However, at least some shells seem to act as though CDPATH ends with :., so, if you say cd foo, you will get ./foo unless some other parent directory listed in your CDPATH contains a foo.  YMMV.

Editor's note: Cygwin seems to support CDPATH autocomplete out-of-the-box (running bash version "4.1.17(9)-release").

Solution 2:

This seems ridiculously complex, but it's the solution I came up with:

function gcd {
  cd $HOME/git/firefly/$1
}

function _gcdcomplete()
{
  local cmd curb cur opts

  # base dir
  git=$HOME/git/firefly/

  # last arg so far
  cur="${COMP_WORDS[COMP_CWORD]}"

  # dirname-esque, but makes "xyz/" => "xyz/" not "."
  curb=$(echo $cur | sed 's,[^/]*$,,')

  # get list of directories (use commened out line for dirs and files)
  # append '/' to directories
  # cmd="find $git$curb -maxdepth 1 -type d -printf %p/\n , -type f -print "
  cmd="find $git$curb -maxdepth 1 -type d -printf %p/\n "

  # remove base dir from list and remove extra trailing /s
  opts=$($cmd | sed s:$git:: | sed s://*$:/:)

  # generate list of completions
  COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  return 0;
}
complete -o nospace -F _gcdcomplete gcd