114

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
Eliah Kagan
  • 119,820
keturn
  • 1,397
  • 4
    If you are affected by this bug please consider voting under the following url (requires login): https://bugs.launchpad.net/ubuntu/+source/bash/+bug/778627/+affectsmetoo – cripton May 24 '12 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... – Jonatan Öström Jun 29 '20 at 22:06
  • 4
    As of August 2020, this bug still exists in Ubuntu 20.04, bash 5.0-6ubuntu1.1. – Naghi Aug 23 '20 at 05: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 '22 at 22:21
  • It looks like in ubuntu 22.04, you need to remove or comment out the completion code at the bottom of ~/bashrc. I then put my options in .bash_aliases. – Juan Aug 16 '23 at 19:46

9 Answers9

99

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.

Eliah Kagan
  • 119,820
Peter V. Mørch
  • 5,897
  • 4
  • 39
  • 42
  • 2
    a version of bash with direxpand is making its way into Precise (12.04): See https://bugs.launchpad.net/bugs/778627 – keturn Mar 31 '13 at 19:48
  • 24
    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 '14 at 06:17
  • 1
    @jozxyqk Did you ever find a way to get that no-path-expansion feature? – Ungeheuer Apr 08 '19 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 '19 at 22:12
  • 9
    user3080602's answer below worked for me - shopt -u progcomp solves the issue without expanding the variable to it's value – Gilthans Nov 27 '19 at 14:14
  • I don't know about Ubuntu, direxpand has its own problems in Fedora. – Jonathan Wakely Dec 12 '19 at 11:49
  • The bad thing is that you have to re-set direxpand option in every new termnal. – Naghi Aug 23 '20 at 10:40
  • I summarize the solution as following: 1- open ~/.bashrc in an editor 2- add this line at the end of the file shopt -s direxpand. 3- save the file, close and open your terminal again; the problem is solved! – Naghi Aug 23 '20 at 14:21
  • @jozxyqk Seems worth mentioning that this is exactly how zsh works out of the box. Seriously thinking of switching now. – Luke Maurer Feb 05 '21 at 21:16
  • @jozxyqk you write "I'm currently using bash 4.4.19 on Ubuntu 18.04 and it just works. Not sure when this changed" If you have the package bash-completion installed, it works because of an Ubuntu patch for this package, specifically this one – philb May 17 '22 at 21:29
  • An important side effect is that this substitues the $variable instead of leaving it intact. This is not desirable if you want to keep it as a variable. – Neinstein Dec 12 '24 at 12:28
46
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

user3080602
  • 591
  • 4
  • 2
6

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.

Eliah Kagan
  • 119,820
rsn86
  • 181
  • 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 '22 at 20:02
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
guntbert
  • 13,485
mba
  • 61
  • 1
    In 12.04 GNU bash, version 4.2.25 this suggestion gives the error: compopt: noquote: invalid option name – arielf Nov 14 '15 at 00: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>/') – Jonathan Wakely Dec 12 '19 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 08 '21 at 06: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). – Jonathan Wakely Aug 06 '21 at 12:18
2

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

for example :

cd /bin
echo ~+/ls
/bin/ls
Tony
  • 141
1

Disabling the shell option 'complete_fullquote' does the job:

shopt -u complete_fullquote
  • $ shopt -u complete_fullquote -bash: shopt: complete_fullquote: invalid shell option name – Anton Gorev Sep 05 '19 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. – typically Sep 09 '20 at 12:14
1

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

philb
  • 162
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.

jozxyqk
  • 1,181
0

Note that the "shopt -u progcomp" proposed above is extremely invasive, as it disables all programmable completions, hence the effects mentioned on make, git, etc.

As it turns out, the problem has now gone through another couple of ups and down. The latest was in Bash 5.1 (seen e.g. in Debian 11), and the full story is here:

https://github.com/scop/bash-completion/issues/290 "Completion of valid paths involving variables adds backslashes"

TL;DR: fixed in 5.2