Bash Too Smart For Its Own Good

So I’m running the latest Ubuntu release in a virtual machine under my main Windows XP machine (it’s a blessing that I no longer need to choose between operating systems these days– I can run them all simultaneously on the same machine if I wish). Today I noticed a feature of Bash that for all I know has been in place for over a decade. I just have never seen it enabled by default in any distribution before. I had to do some research — indeed, one of the first problems in Unix is learning how to ask the right question — but I eventually figured out that the feature is called “Programmable Completion”.

Tab completion is God’s gift to command line navigation. It’s something I always take 10 seconds to carefully explain to anyone who is struggling with the Unix command line for the first time since navigating through a filesystem is agonizing without it. Programmable completion takes tab completion and tries to make it smarter. I first noticed this peculiar behavior on my Ubuntu VMware session today. If there are 2 files in the current directory, xyz.tar.gz and xyz.tar.bz2, then typing ‘tar zxvf x<TAB>’ automatically completes xyz.tar.gz while ‘tar jxvf x<TAB>’ automatically completes to xyz.tar.bz2. I noticed this, thought it was an interesting touch, thought for a moment about how it might work, and immediately wondered what would happen if the underlying mechanism isn’t aware of a mapping that I need.

It didn’t take long before I ran into that eventuality. I was trying to play some impossibly obscure formats with xine. I navigated to the necessary directories only to find that they were apparently empty of any files. I never realized just how important tab completion is to me. Now I’m reading pages of documentation trying to figure out how to disable programmable completion entirely. (It would probably be enough to ask the desktop terminal emulator to run my own Bash config files on startup– I don’t understand why I have to specifically configure such programs to do this.)

Effectively, Bash is making a decision here about what files it thinks I want to see. I’m surprised a Linux distribution would program that kind of behavior by default. How condescending is it when a Microsoft OS tells you that there are entire sets of files that you don’t need to see? Maybe that’s not a fair comparison, as the programmable completion feature is more akin to a list of file filters in a “File Open…” dialog box. Thing is, there’s no obvious way to select “show all files”.

Computer programs get into trouble when they try to anticipate what a normal user needs. More often, such programs have the effect of shaping end user behavior to account for the educated guesses that the computer makes.

11 thoughts on “Bash Too Smart For Its Own Good

  1. dmsc

    Well, fortunately disabling it is easy, edit your .bashrc and comment out the lines that source the “/etc/bash_completion” script.

    The above script is the responsible for the main completion support, you can see “xine” listed there. Also, this script sources the files on “/etc/bash_completion.d/” for added rules.

  2. Multimedia Mike Post author

    If the xterm honored my config files in the first place, this wouldn’t be a problem. When I log into the VM via SSH, I don’t have this problem, my config files are run, giving me the environment I want. The challenge is figuring out how to tell the xterm (GNOME’s terminal in this case) to run the files. I know I have to go through this same nonsense with Konsole on a fresh KDE desktop as well.

  3. SvdB

    Maybe you’re putting your commands in the wrong config file?
    .bash_profile (and .bash_login and .profile) are used only for login shells
    .bashrc is used for all interactive shells

    And “complete -r” removes all tab-completion rules already set.

  4. follower

    Yeah, I’ve noticed the same issue with Ubuntu 7.04 and was thinking surely there must be a way (e.g. push TAB with your thumb or shift or something) to indicate “no, really, I just wanna see what’s there–don’t limit to the auto-complete”.

    –Phil.

  5. Multimedia Mike Post author

    Thanks, SvdB, on both counts. I’ve always wondered why there are all those different .bash* files. Putting stuff in .bash_profile has always seemed to work fine (except for running in an xterm, which always required special steps).

  6. Lars

    Hi there!

    To me it seems better to disable the completion than to remove all rules, because the completion mechanism still runs and eats cycles.
    To disable it use (e.g. in .bashrc):
    shopt -u progcomp

    The rules are still there and you could activate it again with:
    shopt -s progcomp

    Regards
    Lars

  7. DonDiego

    Now that sure is a way to be taught Unix 101, post a blog entry and have people falling over each other explaining the difference between a login and an interactive shell. Mike, you sure found a good way to get this done :)

  8. follower

    So, it seems that pressing Meta-/ will use the non-programmatic completion.

    Interestingly it seems Meta-TAB will search you Bash history for matches.

    You could presumably remap the command on Meta-/ to another TAB combo if you used it enough.

    –Phil “Answering my own questions since 1862”.

  9. Ben

    It’s not just Ubuntu. Debian GNU/Linux (which Ubuntu inherits a lot from) has turned programmable completion on and it’s been driving me absolutely bonkers. In my opinion, hiding filenames from completion is a bug. I only noticed recently since I’ve been carrying around the same .bash* files from machine to machine for years.

    As for getting xterm to run as a login-shell, you can add these two lines to ~/.Xresources:

    ! Xterms are always login shells in order to read .bash_profile
    XTerm.vt100.loginShell: true

    For GnomeTerminal, you can do this: Edit -> Current Profile, then check the box labeled “Run command as a login shell”.

    Personally, I don’t think it’s a good idea to stick everything from .bash_profile into .bashrc, since the .bashrc gets sourced during scp and ftp sessions. There are a lot of things that I *don’t* want run when I’m scp’ing a file across the network. Examples: setterm, xterm title escape sequences, fortune, mesg.

  10. SvdB

    What these commands have in common is that you’d only want to perform them if stdout is a terminal.
    So what I do is put commands like these in an “if [ -t 1 ]; … ; fi” block. (See “help test”.)

    I don’t want my xterms to be login shells. When I login to a machine, I want to be shown the motd, the list of logged in users, and an overview of what folders I have new mail in. I don’t want those for every xterm I open.

  11. sean barrett

    That seems a crazy design; if the “preferred” completion isn’t available, why not try falling back to the normal completion? Surely that’s how I’d have written it the very first time if I’d written it.

    In fact, even then you could get annoyed if there’s a “preferred” completion but you actually want a non-preferred one, but there I might fall back on Windows’ cmd.exe otherwise-lame approach of multiple tab presses cycling through all the matches for what you typed. (Indeed, this whole technique is probably a better fit for Windows cmd.exe approach, where the ‘programmable’ completions could simply come first in the tab-cycle. Actually, I think cmd.exe actually special-case ‘cd’ to only do directories, or at least do them first.)

Comments are closed.