Where do commands come from?
Commands in bash come from any of the following categories:
Bash itself (see builtins)
Bash comes with its own set of commands to allow access to its built-in features such as declaring arrays, reading lines from a file, and other features builtin to bash. We call commands of this category, bash builtin commands, or builtins for short.
Executables in your environment (see external commands)
By default, bash will inherit certain variables by default. This is observed in the case of the PATH variable including locations for executables that are referenced as external commands in bash. That is, if the curl command is in your path, it may be executed from within a bash script the same way as in interactive mode. We call commands of this category, external commands, or commands for short.
User-defined function (see functions)
Before executing external commands and builtins, bash checks if a function is defined. If it is the function is executed as a command. If it doesn’t, it proceeds down the order of precedence for commands. In order to execute function defined outside of a script, they must be declared with the -x attribute; otherwise, they may be included using the . Command. We call commands of this category user-defined functions or functions for short.
What are commands
A command is any word to be treated as a single point of entry of a program within the shell environment. In the case that the command is executed, the command itself and optional arguments are passed in as positional parameters, ${0}, ${1}, ${2}, … The zeroth positional parameter (${0}) designates the command itself and is unchanged in context. That is, unlike positional parameters in functions, ${1}, ${2}, … that may change depending on the context, ${0} is unchanged between function calls.
Commands are scoped depending on the location of declaration and attributes assigned as global, built-in to bash, or local to your bash program.
Here is a list of command types to know.
Builtin commands
These are first-class citizens of the bash universe, including characters such as ‘.’ ‘:’ ‘[‘ ‘]’ and reserved words like declare in bash. You count on these commands, contained in the list of bash builtin commands, to be available to use within your bash script.
Depending on the designation and version number of your bash interpreter some commands may not be available.
External commands
External commands are executables accessible outside of a bash script like curl. Unlike functions, external commands are not stored as variables.
The lower the precedence of a command type, the later the command may be interpreted. External commands have the lowest order of precedence in bash. That is before running an external command, the interpreter bash, will look for functions, then builtins, and finally try to see if a command exists externally. If not, you should see the following error.
In a bash script, functions may override external command behavior if sharing the same name such as we’ve seen previously in curl bash examples. An example of a custom external command using a function follows.
command ${FUNCNAME} …
}
This works because functions have higher precedence than external commands and even bash builtins. The limitation is the allowed characters in a function name.
Note that the above example may be accomplished using an alias as follows.
{
curl …
}
‘
In the case of aliases, the type of command may differ depending on the context in execution, whereas in the case of the custom external commands using function method, the entry point is always a function.
Functions
Functions rule in bash. Before looking at builtins and external commands, bash checks if a function defined by a candidate function name, the first word appearing on a line or after the ; character designating the end of a command line. The only exception is bash variables written in all-caps such as ${FUNCNAME}.
alias curl=‘TEST CURL ALIAS’ # ?
Simple commands
Simple commands are defined in the bash man pages as a word followed by optional arguments. In context, a simple command may be either a builtin, external command, or function.
How to execute commands from within a bash script
Now that we know what types of commands are available, we can expand into how to use them in your scripts. First, we’ll need to know how command precedence works in bash.
Here are some ways to control precedence in a bash script.
Let bash decide
For the most part, especially in the beginning, we just let bash decide which command to use. However, there are cases when your intent may not be interpreted correctly by bash. Such is the case when function names and external commands or builtins overlap.
Execute an external command
Suppose that there is an external command command_name that is available in interactive mode and you wish to use it in a bash script. We can explicitly tell bash that command_name is an external command using the command builtin.
External command examples
External command examples assuming the following are installed:
git
figlet
Example: Get file type and info
file ${infile} # (1,2)
}
# (1) command, file
# (2) infile={Path to file}
Example: Stage modified and new files in git
git add . # (1)
}
# (1) command, git
Example: Create ascii art using figlet
figlet ${message} # (1,2)
}
# (1) command, figlet
# (2) message={Message to display as ascii art}
Execute a builtin command
Suppose that command_name is one of the commands defined as a builtin in bash. To let bash know that we want to run command_name as a builtin we use the builtin builtin.
Builtin command examples
Example: How many builtins?
Example: Phantom declare
declare() { echo oops! ; }
declare –xf declare # ?
}
Conclusion
It is fairly easy to execute a command from within a bash shell script. There are three main command types. Knowing how simple commands are interpreted in bash can lead to improved control over what type of command is executed in runtime.