How to identify shell builtins, aliases and executable files on Linux systems

What exactly is a "builtin" on a Linux system? Let's look at some commands that allow you to recognize builtins and understand exactly what they are -- along with other command types.

shell
Matthew Mendoza (CC BY-SA 2.0)

Shell builtins are commands that are loaded into memory when a shell — such as bash, sh, or zsh — is invoked. The reason for this is that keeping these commands in memory helps ensure that these commands will be run very efficiently whenever someone uses them. They run faster because they don't have to first be loaded into memory. They're "built in."

Determining whether commands that you use are builtins, aliases, or executable files on your system that are loaded as needed requires the use of several interesting commands. These include type, which, and compgen. So, let's take a look at how these commands work and what they can tell us.

The type command

One way to determine if a command is a builtin is to use the type command. If you use this command with a -t option, type will tell you whether the command is an alias, a keyword, a function, a builtin, or a file. Here are some examples:

$ type -t date
file
$ type -t type
builtin
$ type -t ll
alias
$ type -t kill
builtin

In the output above, we see that the date command exists as a regular file on the system. It's loaded into memory when someone uses the command. The type and kill commands, on the other hand, are builtins. They are already loaded in memory — as is the kill command. The ll command is an alias, probably defined in the user's .bashrc file or some other startup file.

With the type command's -a option, you get a little more information — the location of the file associated with the date command and the definition for ll.

$ type -a date
date is /bin/date
$ type -a type
type is a shell builtin
$ type -a ll
ll is aliased to `ls -alF'
$ type -a kill
kill is a shell builtin
kill is /bin/kill

Being a builtin doesn't necessarily mean that a command doesn't exist as an executable file in the file system. Some builtins are only builtins. They're part of the shell. Others are also files. Note that the kill command in the output above is identified both as a builtin and as an executable file.

The type command has other options that can also shed light on commands.

  • -a shows the location of the file that contains the executable and identifies builtins
  • -f suppresses shell function lookup
  • -t identifies a command as an alias, keyword, function, builtin, or file
  • -p displays the names of disk files for non-builtins
  • -P shows the location of files

The which command

Notice that the which command will only tell you about commands that exist as executable files on your system. This command has no insight to offer on builtins except for those that are also executable files and then it only tells you about the files. It has nothing to tell you about builtins:

$ which date
/bin/date
$ which type
$ which alias
$ which kill
/bin/kill

The compgen command

The compgen command is the most useful for providing information on builtins. If you're curious about which of the commands that you use are builtins, try the compgen -b command. It will provide a complete list of builtins. And note that compgen is itself a builtin. It does not exist as a file on the system.

The name compgen is meant to bring the phrase "completion matches" to mind as it attempts to provide information on a series of different requests. The -b option which reports on builtins is only one of them.

Here's an example of compgen listing builtins. Note that I used the column command to make the display a little more appealing.

$ compgen -b | column
.               dirs            kill            source
:               disown          let             suspend
[               echo            local           test
alias           enable          logout          times
bg              eval            mapfile         trap
bind            exec            popd            true
break           exit            printf          type
builtin         export          pushd           typeset
caller          false           pwd             ulimit
cd              fc              read            umask
command         fg              readarray       unalias
compgen         getopts         readonly        unset
complete        hash            return          wait
compopt         help            set
continue        history         shift
declare         jobs            shopt

With different options, the compgen command displays many different types of information.

With -a, compgen lists your aliases:

$ compgen -a | column
c fgrep l. ls which xzfgrep zegrep zgrep
egrep grep ll vi xzegrep xzgrep zfgrep

The alias command will also list your aliases, but with the definition of the aliases as well as their names.

$ alias
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias busy1='yes > /dev/null &'
alias busy2='dd if=/dev/zero of=/dev/null'
alias c='clear'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias list_repos='grep ^[^#] /etc/apt/sources.list /etc/apt/sources.list.d/*'
alias ll='ls -alF'
alias ls='ls --color=auto'
alias rel='lsb_release -a'
alias show_dimensions='xdpyinfo | grep '\''dimensions:'\'''
alias showmem='sudo dmidecode -t 17 | grep '\''Size.*MB'\'' | awk '\''{s+=}'\'' END {print s / 1024 }'
alias sstats='ss -s'

Note that some aliases may be defined in your account's startup files (e.g., .bashrc), while others may be defined in system files and apply to all user accounts.

Only one of the compgen options reports on builtins. The others provide other useful but unrelated information. Here's a list of the compgen command's options:

  • -a lists aliases
  • -b lists shell builtins
  • -c lists commands and aliases
  • -d lists directories
  • -e lists exported shell variables
  • -f lists file and functions
  • -g lists groups
  • -j lists jobs
  • -k lists shell reserved words
  • -s lists services
  • -u lists user aliases
  • -v lists shell variables

Here are some examples of other compgen commands:

$ compgen -c | head -11		<== aliases
alert
c
egrep
fgrep
grep
l
la
list_repos
ll
ls
rel
$ compgen -j			<== jobs
$ ~bin/myloop &
$ compgen -g | head -11		<== groups
root
daemon
bin
sys
adm
tty
disk
lp
mail
news
uucp
$ compgen -v | head -6		<== shell variables (too many to list)
BASH
BASHOPTS
BASHPID
BASH_ALIASES
BASH_ARGC
BASH_ARGV

Wrap-up

There are quite a few commands that identify builtins and allow you to retrieve useful information that sheds light on your working environment on Linux. The type, which, and compgen commands are probably the most useful, though the compgen command's options take you far beyond the task of exploring builtins and executable command files.

Join the Network World communities on Facebook and LinkedIn to comment on topics that are top of mind.
Related:
Now read: Getting grounded in IoT