7

I've played with bash autocomplete now for a while, but couldn't find a solution for my problem. I have a project directory with subfolders like this:

  • projects/ruby/project1
  • projects/ruby/project2
  • projects/rails/project3
  • projects/html/project4

Now I want to have a command, call it cdproject where I can cd in any subfolder within my projects dir and subdirs. And this command should provide a autocomplete feature where I can type cdproject pr --> TAB TAB and then get a list like ruby/project1, ruby/project2, rails/project3...

My problem is how to handle the subdirs. The programm cdproject looks like this

#!/bin/bash
cd $1

The cdproject-autocompletion.bash looks like this

_cdproject()
{
  local cur prev opts
  COMPREPLY=()
  cur="${COMP_WORDS[COMP_CWORD]}"
  prev="${COMP_WORDS[COMP_CWORD-1]}"
  opts=$(ls ~/Dropbox/projects)
  COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  return 0
}
complete -o default -o nospace -F _o  o

And inside my .bash_profile I've sourced the cdproject-autocompletion.bash with

source ~/cdproject-autocompletion.bash

So anyone an idea, how to achieve this? Maybe the opts should return the subdir structure ruby/project1 but then the autocompletion should only work on the last part, the actual project name. And I have no idea how this is possible.

5
  • Doesn't answer your question directly, but something you can look into for changing directories quickly is: github.com/rupa/z Commented Dec 6, 2012 at 18:58
  • What is the behavior you are currently getting? Does it work as is without sub dirs? Commented Dec 9, 2012 at 0:24
  • It now works for one folder, because my script just does a cd ~/Dropbox/projects/$1. But I can't figure out how to include the subdirectories, so that I can directly switch into one subdir. Every project has a different name, maybe thats important Commented Dec 10, 2012 at 15:47
  • Would you consider simply renaming the folders to 1project, 2project etc? That's what I'd do :P Commented Mar 8, 2013 at 20:22
  • The question is old, but here is an update: For now, I use the Z Shell (zsh) along with oh-my-zsh and the plugin z. It provides a pretty good autocomplete feature. See here github.com/rupa/z, github.com/robbyrussell/oh-my-zsh Commented Jul 21, 2015 at 8:02

2 Answers 2

5

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

1

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

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.