96

I have this on the command line:

ln -sf $PWD/wine-

and then I hit Tab to complete the filename. In earlier versions of Ubuntu, this worked just fine to complete the wine- filename (and as a side-effect $PWD would be expanded at that time). But now it turns it in to

ln -sf \$PWD/wine-

which isn't what I meant at all and doesn't complete anything as the file does not literally start with $.

How do I get completion back to the less broken behaviour?

set tells me these are my current settings:

BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
4
  • 4
    If you are affected by this bug please consider voting under the following url (requires login): bugs.launchpad.net/ubuntu/+source/bash/+bug/778627/…
    – cripton
    May 24, 2012 at 17:03
  • 6
    How can this still be a there in 2020? If it understands that it's a path variable so that it expands the filename (which it does for me) it should understand to not escape the $ that makes it a path variable... Jun 29, 2020 at 22:06
  • 4
    As of August 2020, this bug still exists in Ubuntu 20.04, bash 5.0-6ubuntu1.1.
    – Naghi
    Aug 23, 2020 at 5:21
  • "This" is several bugs/ behaviour changes across both Bash itself and bash-completion, and the specific patches that each Linux distributions carry for both of these...
    – philb
    May 17, 2022 at 22:21

8 Answers 8

89

I've found that bash versions >= 4.2.29 have a new direxpand shopt setting. (See man docs/bash.1 if you check out a new bash, or see bash.1 from line 8951)

If one uses Quantal Quetzal 12.10 or otherwise gets hold of (or checks out and builds) a new bash, then:

shopt -s direxpand

Gives me the behavior I want, need and love.

Workaround: In the meantime, Ctrl+Alt+E instead of Tab does what I want too. But is awkward.

BTW, There are several threads called "bash tab variable expansion question?" in gnu.bash.bug. From reading them, I found the info here.

10
  • 2
    a version of bash with direxpand is making its way into Precise (12.04): See bugs.launchpad.net/bugs/778627
    – keturn
    Mar 31, 2013 at 19:48
  • 20
    Would be even better if I didn't have my huge path expanded and could continue using an un-escaped variable with completion.
    – jozxyqk
    Aug 28, 2014 at 6:17
  • 1
    @jozxyqk Did you ever find a way to get that no-path-expansion feature?
    – Ungeheuer
    Apr 8, 2019 at 16:40
  • @Ungeheuer I'm currently using bash 4.4.19 on Ubuntu 18.04 and it just works. Not sure when this changed.
    – jozxyqk
    Apr 26, 2019 at 22:12
  • 8
    user3080602's answer below worked for me - shopt -u progcomp solves the issue without expanding the variable to it's value
    – Gilthans
    Nov 27, 2019 at 14:14
39
shopt -u progcomp

This fixed it for me, it also removed a lot of "intelligent" completion options which I have found get in the way by not completing files that I know are there because the stupid thing thinks I don't want them as arguments to a particular command. ARRRGH

4
  • 1
    This did it for me! It doesn't escape the variable, nor does it expand it. Thanks!
    – Gilthans
    Nov 27, 2019 at 14:12
  • This (u)nsets the shell option progcomp. See here for more info.
    – user643722
    May 28, 2020 at 10:48
  • 1
    This works for the paths, but for example when using make seeing the make-targets is quite convenient, which is lost with this setting. Jun 29, 2020 at 22:07
  • 1
    I also lost support for git tab-completion (e.g. git checkout + Tab, for branch names). Otherwise, it was nice.
    – Carolus
    Jun 4, 2021 at 14:10
6

search _filedir() in the top level bash_completion script and change the line

compopt -o filenames 2>/dev/null

to

compopt -o filenames -o noquote 2>/dev/null
4
  • 1
    In 12.04 GNU bash, version 4.2.25 this suggestion gives the error: compopt: noquote: invalid option name
    – arielf
    Nov 14, 2015 at 0:28
  • To avoid changing the root-owned script, I'm using this in my .bash_profile: eval $(type -a _filedir | tail -n +2 | sed 's/compopt -o filenames 2>/compopt -o filenames -o noquote 2>/') Dec 12, 2019 at 11:50
  • 1
    It now removes backslashes from manually-escaped filenames: ls file\ w [tab] → ls file with space where the expected result is ls file\ with\ space
    – iBug
    Mar 8, 2021 at 6:41
  • In my comment above, the argument to eval should be quoted, and it can be simplified to eval "$(declare -f _filedir | sed 's/compopt -o filenames 2>/compopt -o filenames -o noquote 2>/')" (but this does indeed have the problem that iBug noted in the comment immediately above, so you need to say ls "file w[tab] to expand usefully). Aug 6, 2021 at 12:18
5

On GNU bash, version 4.2.46(2)-release, the options complete_fullquote and noquote aren't available. The cdable_vars option works on cd only; direxpand expands the variable.

What worked best for me was:

shopt -u progcomp

It worked on other commands, besides cd, preserving the variables instead of expanding them.

1
  • 1
    Useless. It completely disables the intelligent completion from /usr/share/bash-completion/completions/ directory. So, now 99% of the things you will type manually.
    – Max_Payne
    Mar 19, 2022 at 20:02
2

For those (like me) with 12.04 can use ~+ instead of $PWD...

for example :

cd /bin
echo ~+/ls
/bin/ls
1

Even with the updated bash, I was finding $ still gets escaped.

  • Removing the bash-completion (1:2.1-3.fc20) package
  • or simply not sourcing /etc/bashrc from ~/.bashrc seemed to fix it.

I suspect I'll now be missing some features I'm normally used to but haven't noticed any yet.


Alternative (at least for Fedora 26), add export BASH_COMPLETION_VERSINFO=0 before sourcing /etc/bashrc. This makes the problematic script think its already been sourced.

1

Disabling the shell option 'complete_fullquote' does the job:

shopt -u complete_fullquote
2
  • $ shopt -u complete_fullquote -bash: shopt: complete_fullquote: invalid shell option name Sep 5, 2019 at 20:34
  • 2
    The option is available for me in bash v5.0.17, but setting it results in undesirable behavior. When I tab-complete "vim ~/.ba" it adds a backslash like "vim \~/.bashrc", which seems similar to the issue OP had in the question. Sep 9, 2020 at 12:14
0

If you do not care for programmable completion (usually installed by bash-completion), then any method mentioned here to disable those will do (like shopt -u progcomp).

If you want Bash to expand the variable when you type TAB, then shopt -s direxpand will do.

If you do not want to use shopt -s direxpand, and want to keep programmable completions from bash-completion, and you have root access, you can apply the same patch as Ubuntu applies, i.e. this patch.

If you do not have root access you can disable the system bash-completion (see bash-completion's README and install a patched version in your $HOME (download and extract the tarball and --configure --prefix=$HOME or similar)

EDIT the above is valid for Bash 4.4.19. It seems Bash 5.0 and above break the whole thing again...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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