I guess my question is where are the configuration files for tab-completion located on an Ubuntu system?
In Ubuntu, the bash-completion library lives in /usr/share/bash-completion/bash_completion
.
When you start a shell, this library can get sourced in a number of ways, e.g.,
If anyone has had this specific problem, or can see plainly what I cannot, how to fix this, and/or why this would occur? (I always want to know why.)
I recently answered a related question over at AskUbuntu (and found your question in the process), so look there for details, but in a nutshell, this is a known bug.
To fix it, you can either:
Replace
[[ ${!2} == \$* ]] && eval $2=${!2}
with
[[ ${!2} == \$\'* ]] && eval $2=${!2}
in the function _quote_readline_by_ref
in the file /usr/share/bash-completion/bash_completion
(not recommended); or
Check out the newest Git version of the bash-completion library and use that - the bug seems to be fixed in this version.
You won't get tab completion inside command substitution working again with either of these solutions, but at least, you won't see that error message any longer.
To actually get tab completion inside command substitution working, you will either have to revert to an earlier Bash version (where I hear it was working), or wait for the library to truly fix that issue with Bash 4.3.
Process substitution results in a special file (like /dev/fd/63
in your example) that behaves like the read end of a named pipe. This file can be opened and read, but not written, not seeked.
Commands that treat their arguments as pure streams work while commands that expect to seek in files they are given (or write to them) won't work. The kind of command that will work is what is usually considered a filter: cat
, grep
, sed
, gzip
, awk
, etc... An example of a command that won't work is an editor like vi
or a file operation like mv
.
gcc
wants to be able to perform random access on its input files to detect what language they are written in. If you instead give gcc
a hint about the input file's language, it's happy to stream the file:
gcc -x c <(echo 'int main(){return 0;}')
The simpler more straightforward form without process substitution also works:
echo 'int main(){return 0;}' | gcc -x c -
Note that this is not specific to bash
. All shells that support process substitution behave the same way.
Best Answer
Unlike
extglob
,nullglob
makes a huge difference in the shell behavior. It means that a word containing wildcard characters that are likely to match nothing result in a word disappearing instead of being kept.In most cases, code that breaks with
nullglob
would also break without it, if a certain directory contains files that happen to match the unquoted pattern. Depending on the pattern, the existence of such files may be more or less likely (and it may be impossible if the scripts controls what file names are present, e.g. because it switches to a temporary directory that it populates).Bash's tab completion is not affected by nullglob by default, but it is affected if you enable programmable completion, because some of the bash code that implements programmable completion is not robust.
Looking at what happens when completing the argument of
ls
withset -x
turned on, I see that the output with and withoutnullglob
starts differing at(working) vs.
with nullglob. See that
eval
line? That's a sign that the argument looked like a glob pattern. The corresponding code is in the__reassemble_comp_words_by_ref
function:[
is a wildcard, so$2[$j]=\${!ref}\${COMP_WORDS[i]}
is a wildcard pattern, and withnullglob
, it's eliminated since it matches nothing. This would also break even withoutnullglob
if the current directory contained a file calledwords0=${!ref}${COMP_WORDSi}
— that's pretty exotic, but it could happen.The fix is to add the missing double quotes:
There are probably other parts of that script that need similar fixes, I haven't investigated further.
This is a bug in bash_completion (not in bash itself). It was reported in 2012 and fixing it is on the roadmap for version 3.0.