Bash Tips: Autocompletion
By
Steer around errors and save yourself some typing by adding autocompletion to your Bash scripts.
The magic word that lets you reduce the number of key presses on the one hand and avoid the potentially fatal consequences of typos on the other is completion. There probably isn’t a command-line user alive today who doesn’t appreciate the Tab key, which completes commands at the start of the line as well as directory names and file names. However, quite a few people are probably blissfully unaware of the double-Tab shortcut – I mean Linux users who stand alone like a lighthouse in an ocean of Windows users. No kindred spirits will look over their shoulders and say: “There’s no need to type ls cd ls …; just type cd Tab-Tab instead, and the shell will show you a list!”
Completion isn’t a core feature of Bash, it’s part of the Readline library. The Readline complete() function triggers automatic completion of a text and is normally linked to the Tab key. Many programs use the Readline library, which explains why the completion mechanism is also available in these tools.
At the command line, the text in front of the cursor is decisive. If it starts with a dollar sign ($), Readline will search the list of variables; a tilde (~) triggers a search in the list of users defined in /etc/passwd, and a commercial at (@) searches in the list of hosts. Text without one of these special characters at the start of the line is interpreted by the completion mechanism as the start of the command – including aliases and shell functions. If nothing else is appropriate, Bash will try file name completion; that is, complete() will try to add the name of a file or directory in the current directory to the text.
To support all this completion, a number of Readline functions run in the background (e.g., complete-command, complete-filename, complete-into-braces, complete-username, complete-hostname, complete-variable). The command
bind -p | grep complete
shows Bash to which key this special feature is bound on the system. Tab is not the only key that triggers completion. Hostname completion can be very useful if you need hostname completion without the @, as in:
scp <file> <targ>Esc Ctrl+Al+Q
Bash then shows you the full name of the target computer:
scp <file> <targetcomputer>
The keyboard shortcut Esc Ctrl+Alt+Q (or M-@ if you have a meta key) is normally linked to complete-hostname and completes the initial characters of a hostname you are entering.
Beware of the Manual
Both hostname completion and user completion have a couple of pitfalls in store for the user. For example, Bash reads the hostname is from the file to which the HOSTFILE variable points. According to the Bash manual, if the HOSTFILE variable is set but empty, Bash will read from /etc/hosts. If the variable is not set, the completion list is empty.
But the Bash manual is wrong here; exactly the opposite is the case: The variable has to be either unset or list-filled with something – the HOSTFILE file doesn’t need to exist to use /etc/hosts as a source. In large environments /etc/hosts is typically empty anyway. In this case, every user can create their own HOSTFILE with their favorites and set the variable in ~/.bashrc.
User completion normally evaluates /etc/passwd. On networks that use a directory service to store usernames and rely on NSS-LDAP, Bash triggers an LDAP query for user completion. It can take ages; Bash appears to freeze. Depending on the size of the organization, a query like ~ Tab-Tab will return a huge number of usernames because it queries all of the users in LDAP! Unfortunately, no environmental variable equivalent to HOSTFILE exists for user completion in this case.
Your Own Completion
To extend the Bash completion system, you can use the built-in Bash complete command. The function isn’t exactly trivial, as you can easily see from the level of detail the man page provides. The easiest part is word completion. A small synchronization script that I wrote accepts a profile as its only argument,
complete -W “home data images baw” syncfiles
telling Bash to complete the possible profile names for the syncfiles command automatically when I press the Tab key. More powerful than -W is the -F option, which expects a shell function as an argument. From the current command line it computes the possible completions and stores them in the COMPREPLY array. Listing 1 shows an example, which I reduced significantly.
Listing 1: Completion with a Shell Function
001 #!/bin/bash 002 003 oocalc_complete() { 004 local ext="ods" 005 local word="$2" 006 007 # Standard completion (filename-completion) 008 local i=0 line 009 declare -a list 010 while read line; do 011 list[i++]="$line" 012 done < <(compgen -f -- "$word") 013 014 # Filter: only filenames with the correct extension 015 local w e 016 for w in "${list[@]}"; do 017 if [ -d "$w" ]; then 018 continue 019 else 020 e="${w##*.}" 021 if [ "$e" = "$ext" ]; then 022 COMPREPLY[i++]="$w" 023 fi 024 fi 025 done 026 } 027 028 complete -o plusdirs -F oocalc_complete oocalc
The current complete specification ensures that Bash only completes directories and ODS files for the oocalc command. First, in lines 8 through 12 the shell function creates a list of all files and directories that normal completion would cover. After this, the script filters out all the inappropriate directories and files. In line 22, valid completions are dumped into the COMPREPLY array, which is unfortunately necessary because the standard complete options, -X and -G, are only designed for filtering filenames and will not cooperate with autocompletion of directory names.
Do-it-Yourself Bash Bashing
Fortunately, the user does not have to type complete definitions for standard commands. For example, openSUSE installs an entire Complete framework. One alternative is the comprehensive bash-completion package, which completes all CLI options for GNU-compatible tools (Figure 1) and valid package names for the RPM command; it even knows the modules in CVS. If you want to tweak this yourself, you will find plenty of examples in the Bash Completion package.
Conclusions
Bash as a programming language gives users a sophisticated, but not entirely self-explanatory, tool. The autocompletion feature described here would suggest that the shell’s interactive mode has some very powerful functions up its sleeve. If you keep a small cheat sheet with the most important function keys next to your PC, you can substantially reduce the need to type.
The Author
Bernhard Bablok works for Allianz Managed Operations & Services SE, where he manages a large data warehouse comprising anything from mainframes to servers with technical performance measuring data. His hobbies are listening to music, riding his bike, and walking, but also Linux in general and object orientation specifically.
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
OSJH and LPI Release 2024 Open Source Pros Job Survey Results
See what open source professionals look for in a new role.
-
Proton 9.0-1 Released to Improve Gaming with Steam
The latest release of Proton 9 adds several improvements and fixes an issue that has been problematic for Linux users.
-
So Long Neofetch and Thanks for the Info
Today is a day that every Linux user who enjoys bragging about their system(s) will mourn, as Neofetch has come to an end.
-
Ubuntu 24.04 Comes with a “Flaw"
If you're thinking you might want to upgrade from your current Ubuntu release to the latest, there's something you might want to consider before doing so.
-
Canonical Releases Ubuntu 24.04
After a brief pause because of the XZ vulnerability, Ubuntu 24.04 is now available for install.
-
Linux Servers Targeted by Akira Ransomware
A group of bad actors who have already extorted $42 million have their sights set on the Linux platform.
-
TUXEDO Computers Unveils Linux Laptop Featuring AMD Ryzen CPU
This latest release is the first laptop to include the new CPU from Ryzen and Linux preinstalled.
-
XZ Gets the All-Clear
The back door xz vulnerability has been officially reverted for Fedora 40 and versions 38 and 39 were never affected.
-
Canonical Collaborates with Qualcomm on New Venture
This new joint effort is geared toward bringing Ubuntu and Ubuntu Core to Qualcomm-powered devices.
-
Kodi 21.0 Open-Source Entertainment Hub Released
After a year of development, the award-winning Kodi cross-platform, media center software is now available with many new additions and improvements.