If you’re getting the error:
-sh: <( compgen -f -X -- 'b' ): No such file or directory
when you’re trying to invoke filename completion, for example like this:
bjb@edouard:/etc$ ls b<tab>
where you typed a b and then tab, to find all the directory entries in /etc that start with b, then you might have the posix option set on your shell while using an old version of bash_completion package. The version that gave me grief was 20080705. Another machine has version 1:1.2-3 and it doesn’t suffer from this problem.
You can check by showing the contents of $SHELLOPTS:
echo $SHELLOPTS
(And getting the package version number: apt-cache policy bash_completion
.)
If the contents of the SHELLOPT shell variable includes the posix
keyword, then you will need to disable posix because the shell completion implementation in bash-completion 20080705 doesn’t seem to be posix compliant.
set +o posix
will turn OFF posix mode, and
set -o posix
will turn ON posix mode.
So to make command line completion work, I had to give the command set +o posix
CORRECTED 2010-12-16
Figuring this out introduced me to an interesting shell construct that I hadn’t seen before. In the old version of /etc/bash_completion, in function _filedir, you see this:
_filedir() { local IFS=$'\t\n' xspec _expand || 0 local toks=( ) tmp while read -r tmp; do [[ -n $tmp ]] && toks[${#toks[@]}]=$tmp done < <( compgen -d -- "$(quote_readline "$cur")" ) if [[ "$1" != -d ]]; then xspec=${1:+"!*.$1"} while read -r tmp; do [[ -n $tmp ]] && toks[${#toks[@]}]=$tmp done < <( compgen -f -X "$xspec" -- "$(quote_readline "$cur")" ) fi COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" ) }
It is the <( some command with output to stdout )
construct that I hadn’t seen before. It represents “process substitution” and the man page says it “is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files. It takes the form of <( list ) or >( list ). The process list is run with its input or output connected to a FIFO or some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion. If the >(list) form is used, writing to the file will provide input for list. If the <(list) form is used, the file passed as an argument should be read to obtain the output of list.”
And also I relearned about the declare -f
which will show you all the function definitions your shell currently knows about.