4

On my Mac, bash (version 3.2.53(1)) autocompletes command-line arguments using files only in the current directory.

On a Linux machine at work, bash (version 4.1.2(1)) autocompletes command-line arguments using files from the current directory and parent directories.

For example, given the directory tree:

/home/pjl/
    bin/
    foo/
        book/

If on my Mac I do:

$ cd foo
$ cd b<TAB>
$ cd book

bash autocompletes only to book. However, when I'm on the Linux machine and do the exact same thing:

$ cd foo
$ cd b<TAB>
bin book
$ cd b

bash presents two choices: book from the current directory and bin from the parent directory.

How can make bash autocomplete only using the current directory (like it does on my Mac)?

On both machines, I do have CDPATH set to:

.:..:../..:../../..:../../../..:../../../../..:/home/pjl/src:/home/pjl

and if I unset CDPATH on the Linux machine, then bash autocompletes using only the current directory (which is what I want); hence I know the bash on Linux is using CDPATH.

But how can I keep CDPATH set (so cd'ing works as before), but not have bash use CDPATH when doing autocompletion?


An alternate acceptable behavior would be to have autocompletion favor the current directory and use CDPATH if and only if nothing in the current directory matches.

  • Maybe this helps: CDPATH Bash completion in OSX – Cyrus Aug 19 '15 at 22:51
  • @Cyrus: no, it doesn't. I want to do the opposite and make Linux behave like OS X (or bash 4.x behave like bash 3.x). – Paul J. Lucas Aug 19 '15 at 23:29
2

The correct way would be to use the following in your ~/.bashrc as @Gilles suggested above (shorter version here):

_my_cd () { CDPATH= _cd "$@";}

A better way would be to check CDPATH if and only if no matches are found locally:

_my_cd () { CDPATH= _cd "$@"; if [ -z "$COMPREPLY" ]; then _cd "$@"; fi;}

This way you get the functionality of programmable completion without it being a nuisance. Do not forget

complete -F _my_cd cd

For some reason /usr/share/bash-completion/bash_completion has -o nospace for cd (even though nospace seems to be default), so you might as well have:

complete -F _my_cd -o nospace cd
2

The culprit is your bash_completion, not your bash version at all.

With the head version from bash_completion repo, cd auto completion include directories under CDPATH.

You can make change directly to your local bash_completion, but it's better to write your own cd auto completion.


If you want a global effect, create a file named /etc/bash_completion.d/cd with the following content:

_cd()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    _init_completion || return

    local IFS=$'\n' i

    compopt -o filenames

    local -r mark_dirs=$(_rl_enabled mark-directories && echo y)
    local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y)

    _filedir -d

    if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
        i=${COMPREPLY[0]}
        if [[ "$i" == "$cur" && $i != "*/" ]]; then
            COMPREPLY[0]="${i}/"
        fi
    fi

    return 0
}
if shopt -q cdable_vars; then
    complete -v -F _cd -o nospace cd
else
    complete -F _cd -o nospace cd
fi

This version got all from the original, exclude the CDPATH part.


If you want to use only for your setting, you can edit .bashrc with the following:

_my_cd () {
  declare CDPATH=
  _cd "$@" 
}

complete -F _my_cd cd

There's some case made bash completion didn't work with CDPATH in your Mac OSX, your bash_completion is too old or you hadn't load it yet.

You can use BASH_COMPLETION_COMPAT_DIR variable to set the location where bash_completion load your custom completion function, the default is /etc/bash_completion.d.

  • When I try to set BASH_COMPLETION_COMPAT_DIR, bash complains that it's a readonly variable. – Paul J. Lucas Aug 20 '15 at 16:47
  • You must set it before you source bash _completion. – cuonglm Aug 20 '15 at 16:50
  • I don't source bash_completion. The Linux machine is a shared machine, FYI, and I don't have super-user permissions. – Paul J. Lucas Aug 20 '15 at 16:58
  • You should check your .bashrc, bash_completion can be sourced from there. Otherwise, just paste the above code into your .bashrc. – cuonglm Aug 20 '15 at 17:00
  • 1
    Why modify a file in /etc rather than use ~/.bashrc? Why not simply _my_cd () { declare CDPATH=; _cd "$@"; }; complete -F _my_cd cd ? – Gilles Aug 20 '15 at 21:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.