Last updated:
💻 Geeky Vibes! Check out our partner WrinkledT: Sustainable Style With a POP 💥 🌈 for the Soul (and the Planet!) 🌎💚

In a shell script or an interactive shell, you may be using shortcut alias or some other commands without knowing if you are using the builtin definition or a local binary. There is an easy way to find out by using the bash builtins type and command.

What is the type and command builtins?

The shell builtins type and command can both display information about a command and how your command, bash function, or bash alias would be interpreted if used as a command name. They are both parts of the POSIX standard, though the type builtin in bash provides more capabilities than the POSIX definition.

By knowing the type of a command you can ensure the proper behavior of your shell script. A command type in bash will be identified either as an alias, keyword, functions, builtin, file, or an empty string for unknown types.

The command builtin can also be used to execute a command by suppressing the shell lookup. This can ensure the use of the on-disk command.

type: usage: type [-afptP] name [name ...]
command: usage: command [-pVv] command [arg ...]

How to find the type of a command?

To find out the type of a shell command, you can simply use the shell type builtin with the syntax type <command_name>. The bash command builtin with the -V option will provide a similar verbose output.

[me@linux ~]$ type echo
echo is a shell builtin
[me@linux ~]$ command -V echo
echo is a shell builtin

In some cases, you may want to check the type of a command in a shell script, though it is not ideal to parse the verbose output of the type or command builtins. Instead, with the bash type builtin, you can use the -t option. Example: type -t date.

Alternatively, the -a option provides all the possible interpretations of a command, including alias, builtin, and function.

A simple example of using the bash type builtin would be with the echo command which comes as a bash shell builtin but is also frequently found as a binary in /bin/echo. Depending on your system, the two echo commands may behave differently. The bash echo builtin command supports the -n, -e, and -E options while the Unix/Mac echo binary only supports the -n option.

[me@linux ~]$ type -t echo
builtin
[me@linux ~]$ type -a echo
echo is a shell builtin
echo is /bin/echo

How to find the path to a local command or check if a command exists?

You can use the bash specific syntax type -p to find the actual path to an external shell command. It is similar to using command -v which is POSIX compliant. Both methods should be preferred in bash to the legacy which command.

You can easily test with a bash if statement whether a command exists or not and get the path for it.

[me@linux ~]$ type -p date
/bin/date
[me@linux ~]$ type -p python
/usr/local/bin/python
[me@linux ~]$ command -v python
/usr/local/bin/python
[me@linux ~]$ if ! command -v python &>/dev/null; then echo "Python not installed"; fi
Python not installed

👉 You can find an example of the type command for a wrapper of the BSD and GNU date command on Mac in my post on How To Format Date And Time In Linux, MacOS, And Bash?

Detailed Examples

You may have set some personnal alias or function in your profile .bashrc. The most common ones are probably dir, ls, ll, etc. In the event you forgot how you defined your alias or function, the easiest way to display the definition isn’t to read your numerous .bashrc definitions but by using the bash builtin type or command. Also, to find out all your currently defined aliases - alias only - simply run alias -p.

[me@linux ~]$ alias -p
alias ll='ls -l'
alias rm='rm -i'
[me@linux ~]$ command -v rm
alias rm='rm -i'
[me@linux ~]$ command -v ll
alias ll='ls -l'
[me@linux ~]$ command -V rm
rm is aliased to `rm -i'
[me@linux ~]$ command -V ll
ll is aliased to `ls -l'
[me@linux ~]# type rm
rm is aliased to `rm -i'
[me@linux ~]# type -t rm
alias
[me@linux ~]# type cp
cp is /bin/cp
[me@linux ~]# type -t cp
file

Another example to compare type, command -v, and command -V using a readlink alias and a custom function for Docker images clean-up.

# .bashrc
alias readlink="greadlink"
dcleanup(){
    docker rm -v $(docker ps --filter status=exited -q 2>/dev/null) 2>/dev/null
    docker rmi $(docker images --filter dangling=true -q 2>/dev/null) 2>/dev/null
}

[me@linux ~]$ type readlink
readlink is aliased to `greadlink'
[me@linux ~]$ type dcleanup
dcleanup is a function
dcleanup () 
{ 
    docker rm -v $(docker ps --filter status=exited -q 2>/dev/null) 2> /dev/null;
    docker rmi $(docker images --filter dangling=true -q 2>/dev/null) 2> /dev/null
}

[me@linux ~]$ command -v readlink
alias readlink='greadlink'
[me@linux ~]$ command -v dcleanup
dcleanup

[me@linux ~]$ command -V readlink
readlink is aliased to `greadlink'
[me@linux ~]$ command -V dcleanup
dcleanup is a function
dcleanup () 
{ 
    docker rm -v $(docker ps --filter status=exited -q 2>/dev/null) 2> /dev/null;
    docker rmi $(docker images --filter dangling=true -q 2>/dev/null) 2> /dev/null
}
💻 Geeky Vibes! Check out our partner WrinkledT: Sustainable Style With a POP 💥 🌈 for the Soul (and the Planet!) 🌎💚
GET UNIQUE TIPS AND THE LATEST NEWS BY SUBSCRIBING TO MY NEWSLETTER.
AND FOLLOW ME ON