While working on a command line, everyone has to do a common task such as typing, which includes commands, its options, input/output file path, and other arguments. Sometimes, we write a wrong command name because of a spelling error in the command name. Also, typing a long file path will be very difficult to remember. For example, if we want to look recursively into the contents of a directory present at the path /dir1/dir2/dir3/dir4/dir5/dir6
, we will have to run the following command:
$ ls -R /dir1/dir2/dir3/dir4/dir5/dir6
We can see that the path of this directory is very long and there is a high chance of making an error while typing the full path. Due to these issues, working on a command line will take a longer time than expected.
To solve all these problems, shell supports a very nice feature called command completion. Along with the other shell, bash also has a very good support of command completion.
Most of the Linux distributions, for example, Fedora, Ubuntu, Debian, and CentOS have a pre-installed bash completion for core commands. If not available, it can be downloaded using the corresponding distribution package manager with the package name bash-completion
.
Command completion in shell allows you to autocomplete the rest of the characters of the partially typed command, suggesting possible options associated with the given command. It also suggests and autocompletes the partially typed file path.
To enable autocompletion feature in bash, the Tab key is used. While typing a command, a single TAB
autocompletes the command if the single command matches, and double [TAB]
lists all the possible commands starting with a partially typed command.
For example:
$ gr[TAB] # Nothing happens $ gre[TAB] # Autocompletes to grep $ grep[TAB][TAB] # Lists commands installed in system and starts with grep grep grep-changelog grepdiff
Now, suppose we want to see the contents of the /usr/share/man/
directory, we will have to type ls /usr/share/man/
. Using bash completion, type the following command:
$ ls /u[TAB]/sh[TAB]/man
Bash completion will auto-complete the missing partial path and the command will become:
$ ls /usr/share/man
The complete
is a shell builtin that can be used to see the available bash completion specification for the available commands in a system. It is also used to modify, delete, and create bash completion.
To know the existing bash completion, use the complete
command with or without the–p
option:
$ complete -p
The following are some of the outputs of the preceding command:
complete cat # No completion output complete -F _longopt grep # Completion as files from current directory complete -d pushd # Completion as directories from current directory complete -c which # Completion as list of all available commands
To see bash completion on these commands, type the following command:
This lists all files/directories, including hidden files/directories:
$ grep [TAB][TAB]
This lists all files/directories, including hidden files/directories:
$ cat [TAB][TAB]
This tries to list all the available commands in a system. Pressing y will display commands and n will display nothing.
$ complete -c which [TAB][TAB] Display all 3205 possibilities? (y or n)
We can also modify the existing bash completion behavior of a given command using the complete shell builtin command.
The following command is used to change the behavior of the which
command to not display any options:
$ complete which $ which [TAB][TAB] # No auto completion option will be shown
The following command is used to change the ls
command tab behavior to show only the directories list as bash completion:
$ ls ~/[TAB][TAB] # Displays directories and file as auto-completion file1.sh file2.txt dir1/ dir2/ dir3/ $ complete -d ls $ ls ~/[TAB][TAB] # Displays only directory name as auto-completion dir1/ dir2/ dir3/
We can remove bash completion specification for a command using the shell builtin complete
with the –r
option.
The syntax is as follows:
complete -r command_name
Consider the following as an example:
$ complete | grep which # Viewing bash completion specification for which complete -c which $ complete -r which # Removed bash completion specification for which $ complete | grep which # No output
If no command_name
is given as an argument to complete -r
, all the completion specifications are removed:
$ complete -r $ complete
The bash-completion package doesn't provide autocompletion feature for any external tools. Suppose that we want to create a tool that has multiple options and arguments. To add a bash-completion feature to its options, we will have to create our own bash completion file and source into it.
For example, package managers such as dnf
and apt-get
have its own bash completion file to support autocompletion for its options:
$ dnf up[TAB][TAB] update updateinfo update-to upgrade upgrade-to $ apt-get up[TAB][TAB] update upgrade
Consider the following shell script as an example:
#!/bin/bash # Filename: bash_completion_example.sh # Description: Example demonstrating bash completion feature for command options function help() { echo "Usage: print [OPTIONS] [arg ...]" echo "-h|--help Display help" echo "-v|--version Display version of script" echo "-p|--print Print arguments" } function version() { echo "Version of shell script application is 0.1" } function print() { echo "Arguments are: $*" } # Parsing command line arguments while [ "$1" != "" ] do case $1 in -h | --help ) help exit 1 ;; -v | --version ) version exit 1 ;; -p | --print ) shift print $@ exit 1 ;; *) help exit 1 esac done
To know about the supported options in bash_completion_example.sh
, we will run the --help
option:
$ chmod +x bash_completion_example.sh # Adding execute permission to script $ ./bash_completion_example.sh --help Usage: print [OPTIONS] [arg ...] -h|--help Display help -v|--version Display version of script -p|--print Print arguments
So, the supported options are -h
, --help
, -v
, --version
, -p
, and --print
.
To write bash completion, information of the following bash internal variables are required:
Bash variables |
Description |
---|---|
|
An array of words that is typed on the command line |
|
An index of the word containing the current cursor position. |
|
An array that holds the completion results that get displayed after pressing [TAB][TAB] |
The compgen
is a shell builtin command that displays the possible completions depending on the options. It is used in shell functions to generate possible completions.
A bash-completion file for our shell script bash_completion_example
will be as follows:
# Filename: bash_completion_example # Description: Bash completion for bash_completion_example.sh _bash_completion_example() { # Declaring local variables local cur prev opts # An array variable storing the possible completions COMPREPLY=() # Save current word typed on command line in cur variable cur="${COMP_WORDS[COMP_CWORD]}" # Saving previous word typed on command line in prev variable prev="${COMP_WORDS[COMP_CWORD-1]}" # Save all options provided by application in variable opts opts="-h -v -p --help --verbose --print" # Checking "${cur} == -*" means that perform completion only if current # word starts with a dash (-), which suggest that user is trying to complete an option. # Variable COMPREPLY contains the match of the current word "${cur}" against the list if [[ ${cur} == -* ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 fi } # Register _bash_completion_example to provide completion # on running script bash_completion_example.sh complete -F _bash_completion_example ./bash_completion_example.sh
As per convention, a bash-completion function name should start with an underscore (_) followed by the name of the application—that is, _bash_completion_example
. Furthermore, we reset the bash variable COMPREPLY
to clean up any previous left out data. Then, we declare and set the cur
variable to the current word of the command line and the prev
variable to the previous word in the command line. Another variable opts
is declared and initialized with all the options that are recognized by an application; in our case, they are -h -v -p --help --verbose –print
. The condition if [[ ${cur} == -* ]]
checks whether the current word is equal to -*
because our option starts with -
followed by any other character. If true
, then display all the matching options using the compgen
shell builtin with the -W
option.
In order to run the created bash completion, the easiest way is to source into source bash_completion_example shell script
and then run the script or command:
$ source ./bash_completion_example Now, execute shell script: $ ./bash_completion_example.sh -[TAB][TAB] -h --help -p --print -v --verbose $ ./bash_completion_example.sh --[TAB][TAB] --help --print --verbose $ ./bash_completion_example.sh –-p[TAB]
Here, --p[TAB]
gets auto-completed to -–print
.
3.16.81.14