Top Qs
Timeline
Chat
Perspective
Bash (Unix shell)
GNU replacement for the Bourne shell From Wikipedia, the free encyclopedia
Remove ads
In computing, Bash is an interactive command interpreter and programming language developed for Unix-like operating systems.[6] It is designed as a 100% free alternative for the Bourne shell sh and other proprietary Unix shells.[7] Bash has gained widespread adoption and is commonly used as the default login shell for numerous Linux distributions.[8]
![]() | This article is in a state of significant expansion or restructuring. You are welcome to assist in its construction by editing it as well. If this article has not been edited in several days, please remove this template. If you are the editor who added this template and you are actively editing, please be sure to replace this template with {{in use}} during the active editing session. Click on the link for template parameters to use.
This article was last edited by Cedar101 (talk | contribs) 6 seconds ago. (Update timer) |
![]() | This article has multiple issues. Please help improve it or discuss these issues on the talk page. (Learn how and when to remove these messages)
|
Created in 1989 by Brian Fox for the GNU Project, it is supported by the Free Software Foundation.[9] Bash (short for "Bourne Again SHell") can operate within a terminal emulator, or text window, where users input commands to execute various tasks.[10][11] It also supports the execution of commands from files, known as shell scripts, facilitating automation.
The Bash command syntax is a superset of the Bourne shell sh command syntax, from which all basic features of the (Bash) syntax were copied. As a result, Bash can execute the vast majority of Bourne shell scripts without modification. Some other ideas were borrowed from the C shell, csh and its successor tcsh, and the Korn Shell, ksh. It is available on nearly all modern operating systems, making it a versatile tool in various computing environments.
Remove ads
Definitions
Summarize
Perspective
![]() |
ASCII, strings and numbers
All input and output at the command line is communicated using printable, human-language characters, such as the letter a or the number 1. One of the earliest devised and most widespread ways of encoding these characters in a consistent manner which computers could understand was a system called ASCII. Today, all modern terminal emulators are capable of understanding all 95 English language printable characters and numerous control characters from the 128 code-point ASCII standard for character encoding. Control characters most commonly seen during a shell session are newline, tab, space and "null."
$ printf 'newline: <%b>\n' $'\n' newline: < > $ printf 'tab: <%b>\n' $'\t' tab: < > $ printf 'space: <%s>\n' " " space: < > $ printf 'null: <%b>\n' $'\0' null: <>
Any series of characters is called a "string." In Unix-like operating systems, all characters, printable and non-printing, except for a few such as the null character and forward slash /, can be used in naming files.
CLI and GUI
In the mid-1960's, one of the primary ways for humans and computers to interact in real time was at a keyboard with a teleprinter: only display of textual characters was possible. In the 1970s, after computer monitors were developed yet before display of graphics was possible, these interfaces were integrated and were known as hardware video terminals. Their interaction paradigm is the basis of what we consider the command-line interface (CLI).
When computers gained the ability to draw graphics on a monitor, graphical user interfaces (GUI's) were designed. Terminal emulators are GUI software programs which create a visual representation of these earlier hardware computer terminals. Today, when a human user initiates a login session, that procedure usually occurs via some graphical user interface.
GNU Readline
In Bash, certain keypress combinations allow a user to operate the terminal emulator in order to move the cursor within the terminal window, search the command history and use tab completion. By default, the keypress combinations in Bash mirror those of the Emacs text editing software.[12] This functionality is provided by a program called GNU Readline and is available in interactive mode only. Default keybindings for control codes commonly seen when using Bash include:
- Ctrl+c - Cancels the current command and presents a new prompt
- Ctrl+d - Closes the current Bash instance, possibly also closing the terminal-emulator
- Ctrl+z - Stop a foregrounded process
- Ctrl+s - Put the terminal to sleep
- Ctrl+w - Wake the terminal
- Ctrl+a - Move the cursor to the beginning of the current commandline
- Ctrl+e - Move the cursor to the end of the current commandline
- Ctrl+w - Remove one word to the left of the cursor
- Ctrl+→ - Move the cursor one word to the right
- Ctrl+← - Move the cursor one word to the left
Vi (text editor) keybindings are also available and can be enabled by running set -o vi
.[13][14]
Comments
Standard comments in Bash are denoted with a hashtag character: #. Any text to the right of the hashtag to the end of the line will be ignored. Inline comments are allowed, but hashtag comments will not print in § xtrace.
$ foo=bar # an inline hashtag comment occurs on the same line as a command. $ set -x $ # a regular comment (no output) $ : "${foo}" + : bar $
Comments denoted with a colon character, :, originated with the Thompson shell. Any arguments to the right of colon : builtin are ignored and the command always returns true. Inline comments are not possible, but colon comments will print in xtrace and any parameters will have been expanded. [15]
Processes
Each operating system (OS) has at its core a program called the kernel which runs commands. Any program running on a computer including the kernel can be described as something called a "process." Processes can be identified and described as having a certain list of "attributes" such as PID, PWD and EUID.
A process identifier attribute, denoted in Bash by the variable dollar $$
, is a unique integer between 300 and approximately , depending on the OS.
Most processes also have a current working directory (CWD) attribute which is denoted in Bash by the variable $PWD
and discoverable with the shell builtin pwd (short for "print working directory").
All processes have attributes which identify their user and group ID's, $UID
and $GID
, and their "effective" user and group ID's, $EUID
and $EGID
.
Processes can have "effective" owner and group identifiers, but files may not.
$ ps -o pid,uid,euid,gid,egid,cmd=Command | grep -e [b]ash -e [P]ID PID USER UID EUID GID EGID Command 3237 liveuser 1000 1000 1000 1000 bash $ declare -p PWD declare -x PWD="/home/liveuser" $
Files and permissions
In Unix-like operating systems, all objects locatable on the file system are considered to be "files."[16][a] This term, "files," is an umbrella jargon which includes text files, binary files, directories, device files which are used to represent computer hardware, symbolic links and hard links between files: most anything locatable on a file-system.
All "files" have a set of file-system permission attributes, such as owner and group memberships, which control how processes may interact with the file. These permissions are user configurable so they're considered a kind of discretionary access control (DAC). File permissions describe whether each of "owner," "group" or "other," may have "read," "write" or "execute" access. When a user, via some process, requests access to a file, the kernel looks at the process's and files's identifying attributes, and at the file's permissions. From there, the kernel determines whether and how any particular user process may interact with any particular file.
$ ls -l ~/.bashrc -rw--r--r--. 1 liveuser liveuser 7597 Aug 11 20:01 /home/liveuser/.bashrc $
In Unix-like OS's, a written representation of a file's discretionary access control (DAC) permissions is called a "mode."[17]
Shell builtin umask
allows the user to define a default set of DAC permissions for all files created thereafter.[18]
The standard file permission is determined by the mask for new file creation. The value of this mask can be displayed using the
umask
command. Instead of adding the symbolic values to each other, as withchmod
, for calculating the permission on a new file they need to be subtracted from the total possible access rights.
Paths
In Unix-like OS's, files, hardlinks, device nodes, etc., (i.e., "files") are sorted into directories that form a hierarchical file structure which is nested in a "parent" and "child" manner. The base of the hierarchy is called the "root directory" which is denoted by one forward slash: /.
On the command line, a file can be identified using its full filename or an abbreviated filename.[19]
When the kernel searches for a directory, the starting point is the leftmost character of directory name.
For full filenames, or "absolute paths," the leftmost directory is known positively: it's the filesystem root directory, /
.
For abbreviated filenames, or "relative paths," as shorthand on the commandline the current working directory (CWD) can be referred to as .
, and its parent directory as ..
.[b]
If a shell process attempts to locate any filename that begins with the string ./
, it will only search in the current working directory of that process.
$ realpath -e . .. /home/liveuser /home $
The $PATH
variable will be discussed in detail in the next section, § Execution, and in § umask and mode of permissions
Execution
"Execution" of a given program occurs when a user (or some other program) asks the operating system to act upon the instructions contained in the given program.
By default, Bash reads user code one line at a time, interprets any newline or semi-colon character ;
as the end of the current command, and executes commands in sequence.
If an interactive command extends beyond the width of the terminal emulator, it's usually possible to keep typing and the command will wrap around.
To extend a command beyond a newline onto an additional line, it's necessary that the final character of the first line be an unescaped backslash, \
, which signals "line continuation."
Bash always finishes parsing and executing one full command before moving on to and beginning with the parsing of the next command.
When Bash attempts to locate a command for execution, the directories it searches are those listed in the $PATH
variable and the current working directory.[20]
$ foo=aa bar=bb quux=cc zork=dd; set -o xtrace $ : "${foo}"; : "${bar}" + : aa + : bb $ : "${quux}" \ > : "${zork}" + : cc : dd $
Users and PS1
A user account can be created for either a human or a programmatic user. In Unix-like OS's, there are two kinds of users: "privileged" and "regular." A privileged user, such as "root" or the operating system kernel, is allowed to do anything whatsoever on the machine. Unprivileged users are limited in various ways.
When an interactive shell session waits for user input, often within a terminal emulator connected to a peripheral keyboard, by default it prints a particular string of characters to the screen.
In Bash, the value of this waiting-string is held in the shell variable $PS1
.
For regular users a common default value for $PS1
is the dollar character, $.[c]
For the superuser a common default value is hashtag (#)
$ sudo --login --user root [sudo] password for liveuser: # vim /home/liveuser/names.txt # exit $ grep -e bob ./names.txt grep: ./names.txt: Permission denied
Remove ads
Modes
Summarize
Perspective
Programming paradigm
Although most users think of the shell as an interactive command interpreter, it is really a programming language in which each statement runs a command. Because it must satisfy both the interactive and programming aspects of command execution, it is a strange language, shaped as much by history as by design.[21]
Bash is an imperative language.
Interactive and non-interactive modes
As a command processor, Bash can operate in two modes: interactive or non-interactive. In interactive mode, commands are usually read from a terminal emulator. In non-interactive mode, which facilitates automation, commands are usually read from named files known today as shell scripts. When executed as a standalone command at the command-line interface (CLI), by default Bash opens a new shell in interactive mode.
Scripts
Shell scripts are text files that contain code, often commands, intended to be read and acted upon by some particular interpreter in a batch process in a non-interactive mode and without any further user interaction. Interpreted scripts are programs that do not require their source code to be compiled: all of the relevant source code is contained within the script. There are many programs which can serve as an script interpreter: Perl, Ruby, Python, AWK, etc. Interpreted scripts are most often written for Unix shells.
The first two characters of the first line of any (executable) shell script begins with a something called a hash-bang: literally the characters hashtag (#) and bang (!) side by side.
$ cat ./example.sh #! /bin/env bash echo foo exit $
If a script is intended to be run by a user as a stand-alone program on the commandline, then it is referred to as an "executable." By convention, the filenames of executable unix shell scripts are identified the suffix .sh. The "execute" bit can be enabled on a shell script with the utility chmod:
$ ls -l ./example.sh -rw-r--r--.1 liveuser liveuser 32 Aug 3 22:33 example.sh $ ./example.sh bash: ./example.sh: Permission denied $ chmod 0744 ./example.sh $ ls -l ./example.sh -rwxr--r--.1 liveuser liveuser 32 Aug 3 22:33 example.sh $ ./example.sh foo $
source builtin
With the source
, or synonymous .
, command, Bash can read and execute shell commands from files which are not marked as executable, which do not have hash-bangs, and which do not have the file extension .sh.
Such files are known as "source files" or "dotfiles."
In Unix, file names which begin with a "dot," such as ~/.bashrc are considered "hidden files."
Login and non-login shells
Bash can be executed as a login shell, or "session leader," in both interactive and non-interactive modes via the --login
option.
"Logging in" requires user authentication.
For this reason, only one login shell exists per user session.
In GNU/Linux, a user's login shell is identified in the /etc/passwd file.
$ awk -F ':' '$1 ~ /root/' /etc/passwd root:x:0:0:Super User:/root:/bin/bash
When a human user initiates a login session, this procedure often occurs in a graphical user interface (GUI). When a user opens a terminal emulator, the emulator executes a non-login instance of the user's login shell.
Logging out of a shell session from within a terminal emulator can be accomplished with the exit command or, by default in Bash, pressing Ctrl+d.
Startup source files
When Bash starts, it uses source
to execute commands in a variety of dotfiles (see lists below).[22]
These dotfiles, unlike shell scripts, typically have neither the execute permission enabled nor an hash-bang.
By default Bash will source a somewhat different set of files, and in a different sequence, depending on:[23]
- How bash is called
- interactively, non-interactively, invoked with name
sh
- interactively, non-interactively, invoked with name
- Which options are used
--login
,--rcfile
,--norc
,--posix
- Which environment variables are defined
BASH_ENV
,ENV
, and
- Which files exist
/etc/profile
~/.bash_profile
~/.bash_login
~/.profile
~/.bash_logout
, and~/.bashrc
among others.
Of course, any startup file can also execute commands from any other file. Startup files can affect shell behavior, terminal emulators, the X window system and the window manager.
POSIX mode
The POSIX IEEE 1003.1 standard specifies a common set of definitions that any shell system application (bash, dash, zsh, etc.) may conform to.
Any shell user script (./myscript.sh
) written in conformance with POSIX guidelines should be executable by any shell system application that has implemented the POSIX specification.
As a result, there can be a reasonable expectation that POSIX-compliant scripts can be executed with success on any Unix or Unix-like operating systems which implements the POSIX standard (Linux, OpenBSD, Oracle Linux, HP-UX, etc.).
These scripts are considered "portable" as they are and without any further modifications.
The portion of POSIX that applies to shells and command line utilities is a subset of a larger group of POSIX standards that further specify how terminals and terminal emulators aught to function in order to also be considered portable.
When Bash is operating in POSIX mode, fewer features are available but the resulting code can be executed on a greater variety of operating systems.
To enable POSIX mode at the initialization of an interactive shell, Bash can be executed as either sh
, bash --posix
or bash -o posix
.[24]
To cause a script to be initialized in POSIX mode, one would use the either the hashbang #! /bin/env sh
or the less portable #!/bin/sh
.
When an instance of Bash is operating in POSIX mode, the environment variable $POSIXLY_CORRECT
is defined, and the value of the environment variable $SHELLOPTS
includes the string posix.
$ declare -p POSIXLY_CORRECT bash: declare: POSIXLY_CORRECT: not found $ sh $ declare -p POSIXLY_CORRECT declare -- POSIXLY_CORRECT="y" $
The full list of features available in Bash which are not specified by POSIX is considerable.[25] Here is a partial list:
- Any arrays other than the array of positional parameters,
$@
, are not POSIX - The double bracket extended test construct,
[[...]]
, is not POSIX[...]
and test are POSIX
- One of the double-parentheses arithmetic-evaluation syntaxes,
((...))
, is not POSIX$((...))
is POSIX
- Brace expansion,
kernel{,-headers}
, is not POSIX - Dynamic scoping of parameters and the local builtin are not POSIX
- Process substitution,
<(...)
, is not POSIX - Certain string-manipulation operations in Parameter Expansions are not POSIX
- Most Bash builtin commands are not POSIX
- The command
enable -s
prints the list of Bourne Special Builtins, which are POSIX$ enable -s | wc --lines 16 $ enable | wc --lines 61
- The enable builtin itself is not POSIX
- In Bash, in non-POSIX mode, the
.
and source builtins are synonymous- The
.
(i.e., 'dot') builtin is POSIX, however - The source builtin is not POSIX
- The
- The command
- The
$EPOCHSECONDS
and$EPOCHREALTIME
shell variables are not POSIX[26]
System commands which are available in modern Unix-like operating systems, and which are also specified by POSIX may have fewer option flags or fewer relevant environment variables available under POSIX.
Because of these and other differences, modern (version 5) Bash shell scripts are rarely runnable "as-is" under the Bourne or legacy Korn shell interpreters. Scripting with portability in mind is becoming less common as GNU/Linux becomes more widespread.[24][27]
Code that is valid syntax in Bash and yet is not specified by POSIX is called a "bashism." The program checkbashisms can be used to make sure that a script can be executed in Debian Linux without any portability errors.[28] Vidar Holen's shellcheck is another static linter written in Haskell which can parse script syntax for compatibility with any or all of bash, dash, ksh, and Bourne sh.[29] The syntax requirements for each shell are each a little different. For example, Debian's policy allows some extensions in their scripts (as they are in the dash shell),[27] while a script intending to support pre-POSIX Bourne shells, like autoconf's configure, are even more limited in the features they can use.[30]
Compatibility modes
Bash-4.0 introduced the concept of a shell compatibility level, specified as a set of options to the shopt builtin (compat31, compat32, compat40, compat41, and so on). There is only one current compatibility level – each option is mutually exclusive. The compatibility level is intended to allow users to select behavior from previous versions that is incompatible with newer versions while they migrate scripts to use current features and behavior. It's intended to be a temporary solution.[31]
Privileged mode
In Bash, "privileged mode" is a rarely used option inherited (perhaps?) from the SVR4.2 UNIX System V shell (circa 1992).[32]
It can be enabled with set -p
and disabled with set +p
.[33]
When privileged mode is enabled, the $SHELLOPTS
shell variables includes the string, "privileged."
Extended debugging mode
Enabled via bash --debugger
at invocation or via shopt -s extdebug
during either interactive or non-interactive modes. Uses a separate program called bashdb.
extdebug is not available in POSIX mode. See documentation for more information.
See also § Debugging.
Remove ads
Observability
Summarize
Perspective
xtrace
When xtrace is enabled, simple debugging content is printed to the terminal.
It can be enabled with set -o xtrace
or set -x
, and disabled with set +o xtrace
, set +x
or set -
.
These options are also accepted at the commandline and at hash-bangs: #!/bin/bash -x
, etc.
$ bash -x
$ echo $(( 2 + 2 ))
+ echo 4
4
$ set -- 1 2 3
$ printf '<%s>\n' "$@"
+ printf '<%s>\n' 1 2 3
<1>
<2>
<3>
$
The xtrace is specified by POSIX. See also § Debugging.
verbose
Rarely used.[34]
Exit codes
When bash executes commands, exit status codes, also called "return codes," are produced which can offer some insight into the manner in which a program ceased running.
The value of the most recently captured exit code is held within the shell parameter, 'question mark:' $?
.
In non-arithmetic contexts, (i.e., most of the time) the numerical or "Boolean" value of "true" is zero (0), and the value of "false" is one (1).
When a system command has executed, the intended meaning of its exit status can most often be found in its man page; usually a zero indicates success and a nonzero exit status indicates some kind of failure condition or partial success.
ping
is a well known command with three meaningful exit codes: 0, 1, and 2.
In Bash, within arithmetic contexts, the numerical truth values are reversed: "true" is one and "false" is zero.
An arithmetic context can usually be identified by the syntax ((...))
or $((...))
.
If an arithmetic statement evaluates to the integer zero, then the statement is considered "true," and the exit code is one.
If the statement evaluates to any number other than zero the arithmetic statement is "false" and the exit code is zero.
Not all Linux/UNIX commands provide meaningful exit codes beyond zero and one, and there is no standard system for definitions of exit codes in Linux.
$ true; echo "$?" # Exit code means "true" 0 $ false; echo "$?"; echo # Exit code means "false" 1 $ $ bash -c 'exit 99'; printf 'exit-code: %d\n\n' "$?" exit-code: 99 $ $ (( 1 - 1 )); printf '%d\n' "$?" # This exit code means "true" 1 $ (( 1 + 1 )); printf '%d\n' "$?" # ...and this exit code means "false" 0
Signals
Signaling is a means of inter-process communication.
When bash is interactive, in the absence of any traps, it ignores SIGTERM (so that
kill 0
does not kill an interactive shell), and catches and handles SIGINT (so that the wait builtin is interruptible). When bash receives SIGINT, it breaks out of any executing loops. In all cases, bash ignores SIGQUIT. If job control is in effect, bash ignores SIGTTIN, SIGTTOU, and SIGTSTP.[35]
Bash utilizes the trap builtin to catch and process signals.[36]
Signals can be sent to a process using the kill builtin or using the system binary of the same name.
There are a few signals which are only available from within Bash as GNU extensions: ERR, EXIT, RETURN and DEBUG. These signals can only be sent and handled by shell builtins.
Job control
The Bash shell has two modes of execution for commands: batch (asynchronous), and concurrent (synchronous). To execute commands in batch mode (i.e., in sequence) they must be separated by the character ;, or on separate lines:
$ command1; command2 $ command3 $
In this example, when command1 is finished, command2 is executed, and when command2 has completed, command3 will execute. A background execution of command1 can occur using symbol & at the end of an execution command, and process will be executed in background while immediately returning control to the shell and allowing continued execution of commands.
$ command1 & $
Or to have a concurrent execution of command1 and command2, they must be executed in the Bash shell in the following way:
$ command1 & command2 $
In this case command1 is executed in the background & symbol, returning immediately control to the shell that executes command2 in the foreground. A process can be stopped and control returned to bash by typing Ctrl+z while the process is running in the foreground.[37] A list of all processes, both in the background and stopped, can be achieved by running jobs:
$ jobs [1]- Running command1 & $
In the output, the number in brackets refers to the job id. The plus sign signifies the default process for bg and fg. The text "Running" and "Stopped" refer to the process state. The last string is the command that started the process.
The state of a process can be changed using various commands. The fg command brings a process to the foreground, while bg sets a stopped process running in the background. bg and fg can take a job id as their first argument, to specify the process to act on. Without one, they use the default process, identified by a plus sign in the output of jobs. The kill command can be used to end a process prematurely, by sending it a signal. The job id must be specified after a percent sign:
$ sleep 100 & [1] 4904 $ kill %1 $ jobs [1]+ Terminated sleep 100 $
Job control, also known as "Monitor mode," is enabled by default in interactive shells, and can be disabled with set +m
.
Values of parameters
There are many different implementations of echo. Some have the -e
option, and some don't.
The list of options is not uniform across implementations, though echo and printf are both specified by POSIX.
If a scripter wishes to know the precise value of a string contained by a variable, then the most consistent way of doing so is to use printf.
For any string containing any character (besides null?) including digits, the format specifier is %s.
$ foo=abc bar=123 $ printf '<%s>\n' "${foo}" "${bar}" <abc> <123> $
For digits only, the format specifier is %d.
$ printf '<%d>\n' "${foo}" "${bar}" bash: printf: abc: invalid number <0> <123> $
With printf, a newline is never included in the output unless the scripter includes a newline in the format string. In the example below, where a newline has been omitted from the format string, the value of PS1 is printed on the same line as the output of the previous command.
$ printf '<%s>' "${foo}" "${bar}" <abc><123>$
Another very consistent method is to use declare -p
.
The output of declare -p
can be reused as input.
However, not all variables and parameters can be printed using declare -p
, for example, the values of the Special Parameters.
The Special Parameter hashtag, "$#"
, reports how many Positional Parameters are currently defined.
$ declare -p foo bar declare -- foo="abc" declare -- bar="123" $ declare -p "$#" bash: declare: 0: not found $
For a full string of input at an interactive shell...
$ declare -p #
...the hashtag would be interpreted by Bash as an inline comment.
With the comment and all text to the right of it removed, the command that Bash would execute would be declare -p
.
This command would, according to help declare
, "display the values and attributes of each NAME," i.e., each variable, and, "if no NAMEs are given, display the values and attributes and values of all variables," which can be over 100 lines of output.
On the other hand, printf cannot display variables' attributes. See also § Debugging.
$ readonly foo $ declare -p foo declare -r foo="abc" $ printf '<%s>' "${foo}" <abc> $
Environment
![]() | This article contains instructions or advice. (January 2019) |
Configurable execution environment(s):[38]
- Shell and session startup files such as
~/.bashrc
and~/.profile
(i.e., dotfiles); - Settings (set built-in) and shell options (shopt built-in) which alter shell behavior;
Shell and session startup Files (a.k.a., "dot files")
When Bash starts, it executes the commands in a variety of dot files.[22]
Unlike Bash shell scripts, dot files do typically have neither the execute permission enabled nor an interpreter directive like #!/bin/bash
.
- Legacy-compatible Bash startup example
The example ~/.bash_profile
below is compatible with the Bourne shell and gives semantics similar to csh for the ~/.bashrc
and ~/.bash_login
.
The [ -r filename ] && cmd
is a short-circuit evaluation that tests if filename exists and is readable, skipping the part after the &&
if it is not.
[ -r ~/.profile ] && ~/.profile # set up environment, once, Bourne-sh syntax only if [ -n "$PS1" ]; then # are we interactive? [ -r ~/.bashrc ] && ~/.bashrc # tty/prompt/function setup for interactive shells [ -r ~/.bash_login ] && ~/.bash_login # any at-login tasks for login shell only fi # End of "if" block
- Operating system issues in Bash startup
Some versions of Unix and Linux contain Bash system startup scripts, generally under the /etc
directory.
Bash executes these files as part of its standard initialization, but other startup files can read them in a different order than the documented Bash startup sequence.
The default content of the root user's files may also have issues, as well as the skeleton files the system provides to new user accounts upon setup.
The startup scripts that launch the X window system may also do surprising things with the user's Bash startup scripts in an attempt to set up user-environment variables before launching the window manager.
These issues can often be addressed using a ~/.xsession
or ~/.xprofile
file to read the ~/.profile
— which provides the environment variables that Bash shell windows spawned from the window manager need, such as xterm or Gnome Terminal.
Remove ads
Commands
Summarize
Perspective
Aliases
Keywords
function
- Bash function declarations which include this particular keyword are not compatible with Bourne/Korn/POSIX scripts, however, Bash does accepts the function declaration syntax used by Bourne, Korn and POSIX-compliant shells.
Functions
Builtin commands
- Various Built-In Commands:
- POSIX Special builtins:[39]
- cd, pwd, etc.
- set[40]
- Xtrace: [
set -x
|set -o xtrace
]. The shell's primary means of debugging. Both xtrace and verbose can be turned off at the same time with the commandset -
. - Verbose: [
set -v
|set -o verbose
]. Prints a command to the terminal as Bash reads it. Bash reads constructs all at once, such as compound commands which include if-fi and case-esac blocks. If aset -v
is included within a compound command, then "verbose" will be enabled the next time Bash reads code as input, i.e., after the end of the currently executing construct.[41] - Both xtrace and verbose can be turned off at the same time with the command
set -
.
- Xtrace: [
- shopt[42]
- expand-aliases: On by default in interactive shells. Some developers discourage its use in scripts.
- POSIX Special builtins:[39]
PATH and system commands
Command lookup
- Command position: after expansions, the first word of the full text of the command line.
- Command name lookup is performed, in the following order:
- Commands internal to the shell:
- Shell aliases,
- Shell reserved words,
- Shell functions, and
- Shell built-in commands;
- Commands external to the shell, using the PATH shell variable:
- Commands internal to the shell:
- The resulting string is executed as a command.
Remove ads
Control structures
Summarize
Perspective
Pipelines
Subshells
Subshells: (...)
;
Logical operators
- AND (
&&
) - OR (
||
) - NOT (
!
)
Bash supplies "conditional execution" command separators that make execution of a command contingent on the exit code set by a precedent command. For example:
$ cd "$SOMEWHERE" && ./do_something || echo "An error occurred" >&2
Where ./do_something
is only executed if the cd (change directory) command was "successful" (returned an exit status of zero) and the echo command would only be executed if either the cd or the ./do_something
command return an "error" (non-zero exit status).
Compound commands
Bash also supports if ... fi
and case ... esac
forms of conditional command evaluation.[e]
Iteration
- while, until, and select loop compound commands;
- Arithmetic C-style and list-enumerating for loop compound commands; and
- continue, break, return, and exit flow control commands;
Testing
Built in commands for testing file attributes, comparing string and integer values, etc.:
- Traditional test command,
- Traditional single bracket test:
[
, - Modern double bracket test:
[[...]]
, which includes advanced features:- Extended regular expression and extglob matching
- Lexicographic comparisons with
<
and>
;
((...))
numeric evaluation and testing; this includes almost all "C" language operators for arithmetic and numeric comparison;
For all commands the exit status is stored in the special variable $?
.
Regular Expressions
Bash 3.0 supports in-process regular expression matching using a syntax reminiscent of Perl.[44]
Regexp matching is limited to strings on the right side of the =~
operator in the [[..]]
extended test construct.[45]
[[ $line =~ [[:space:]]*(a)?b ]]
means values for line like ‘aab’, ‘ aaaaaab’, ‘xaby’, and ‘ ab’ will all match, as will a line containing a ‘b’ anywhere in its value.
Remove ads
Data manipulation
Summarize
Perspective
Word Splitting
Split into words (i.e., word splitting)
Quoting
According to quoting rules, including ANSI-C quoting $'...'
.
Unicode
Support for Unicode in echo -e
and ANSI-C quoting.
Brace Expansion
$ echo kernel{,-headers} kernel kernel-headers
Brace expansion, also called alternation, is a feature copied from the C shell. It generates a set of alternative combinations.[46] Generated results need not exist as files. The results of each expanded string are not sorted and left to right order is preserved:
$ echo a{p,c,d,b}e ape ace ade abe $ echo {a,b,c}{d,e,f} ad ae af bd be bf cd ce cf
Users should not use brace expansions in portable shell scripts, because the Bourne shell does not produce the same output.
$ # bash shell $/bin/bash -c 'echo a{p,c,d,b}e' ape ace ade abe $ # A traditional shell does not produce the same output $ /bin/sh -c 'echo a{p,c,d,b}e' a{p,c,d,b}e
When brace expansion is combined with wildcards, the braces are expanded first, and then the resulting wildcards are substituted normally. Hence, a listing of JPEG and PNG images in the current directory could be obtained using:
ls *.{jpg,jpeg,png} # expands to *.jpg *.jpeg *.png – after which, # the wildcards are processed echo *.{png,jp{e,}g} # echo just shows the expansions – # and braces in braces are possible.
In addition to alternation, brace expansion can be used for sequential ranges between two integers or characters separated by double dots. Newer versions of Bash allow a third integer to specify the increment.
$ echo {1..10} 1 2 3 4 5 6 7 8 9 10 $ echo {01..10} 01 02 03 04 05 06 07 08 09 10 $ echo file{1..4}.txt file1.txt file2.txt file3.txt file4.txt $ echo {a..e} a b c d e $ echo {1..10..3} 1 4 7 10 $ echo {a..j..3} a d g j
When brace expansion is combined with variable expansion (a.k.a., parameter expansion and parameter substitution) the variable expansion is performed after the brace expansion, which in some cases may necessitate the use of the eval built-in, thus:
$ start=1; end=10 $ echo {$start..$end} # fails to expand due to the evaluation order {1..10} $ eval echo {$start..$end} # variable expansion occurs then resulting string is evaluated 1 2 3 4 5 6 7 8 9 10
Tilde Expansion
Tilde expansion ~
,
Parameter and variable expansion
- Type
- Shell parameters
- Environment variables
- User variables
- Scope
- Arrays
- Indexed arrays: size is unlimited.
- Associative arrays: via
declare -A
[g]
- Parameter Expansion
- Expansion syntaxes which can perform some tasks more quickly than external utilities, including, among others:
- Pattern Substitution
${foo//x/y}
forsed '
,s/x/y/g
'
- Remove Matching Prefix or Suffix Pattern
${bar##[a-zA-Z0-9]*}
forcut -c8-
,
- Enumerate Array Keys
${!array[@]}
, and
- Display Error if Null or Unset
${var:?error message}
,
Pathname expansion
Pathname expansion, i.e., shell-style globbing and pattern matching using *
, ?
, [...]
.[h]
Locales
Remove ads
Process redirections and parsing
Summarize
Perspective
Command substitution
Command substitution: $(...)
,
Process substitution
Process substitution, <()
or >()
, when a system supports it:
Bash supports process substitution using the <(command)
and >(command)
syntax, which substitutes the output of (or input to) a command where a filename is normally used.
(This is implemented through /proc/fd/ unnamed pipes on systems that support that, or via temporary named pipes where necessary).
Arithmetic expansion
Arithmetic expansion, ((...))
or $((...))
, including
- Integer arithmetic in any base from two to sixty-four, although
- Floating-point arithmetic is not available from within the shell itself (for this functionality, see current versions of bc and awk, among others),
Bash can perform integer calculations ("arithmetic evaluation") without spawning external processes.
It uses the ((...))
command and the $((...))
variable syntax for this purpose.
Redirection
Redirections of Standard Input, Standard Output and Standard Error data streams are performed, including
- File writing,
>
, and appending,>
, - Here documents,
<<
, - Here strings,
<<<
, which allow parameters to be used as input, and - A redirection operator,
>
, which can force overwriting of a file when a shell's noclobber setting is enabled;
Its syntax simplifies I/O redirection.
For example, it can redirect standard output (stdout) and standard error (stderr) at the same time using the &>
operator.
This is simpler to type than the Bourne shell equivalent 'command > file 2>&1
'.
Bash supports here documents.
Since version 2.05b Bash can redirect standard input (stdin) from a "here string" using the <<<
operator.
Command parsing
- Comments are ignored, from an unquoted
#
(hash) to the end of the same line; - Commands are parsed one line at a time:
- Control structures are honored, and
- Backslash
\
escapes are also honored at the ends of lines;
- Split into words (i.e., word splitting) according to quoting rules,
- Including ANSI-C quoting
$'...'
;
- Including ANSI-C quoting
- Seven kinds of expansions are performed in the following order on the resulting string:
- (Step 1) Brace expansion
kernel{-headers}
, - (Step 2) Tilde expansion
~
, - (Step 3) In a left-to-right fashion:
- Parameter and variable expansion
$foo
or${bar}
, including- Dynamically scoped variables,
- Indexed arrays of unlimited size,
- Associative arrays via
declare -A
, and - Expansion syntaxes which can perform some tasks more quickly than external utilities, including, among others:
- Pattern Substitution
${foo//x/y}
forsed '
,s/x/y/g
'
- Remove Matching Prefix or Suffix Pattern
${bar##[a-zA-Z0-9]*}
forcut -c8-
,
- Enumerate Array Keys
${!array[@]}
, and
- Display Error if Null or Unset
${var:?error message}
,
- Pattern Substitution
- Command substitution:
$(...)
, - Process substitution,
<()
or>()
, when a system supports it: - Arithmetic expansion,
((...))
or$((...))
, including- Integer arithmetic in any base from two to sixty-four, although
- Floating-point arithmetic is not available from within the shell itself.[i]
- Parameter and variable expansion
- (Step 4) Word splitting (again),
- (Step 5) Pathname expansion, i.e., shell-style globbing and pattern matching using
*
,?
,[...]
,[h] and Quote removal;
- (Step 1) Brace expansion
- Redirections of Standard Input, Standard Output and Standard Error data streams are performed, including
- File writing,
>
, and appending,>>
, - Here documents,
<<
, - Here strings,
<<<
, which allow parameters to be used as input, and - A redirection operator,
>
, which can force overwriting of a file when a shell'snoclobber
setting is enabled;
- File writing,
- Command name lookup is performed, in the following order:
- Commands internal to the shell:
- Shell aliases,
- Shell reserved words,
- Shell functions, and
- Shell built-in commands;
- Commands external to the shell:
- The resulting string is executed as a command.
- Commands internal to the shell:
Remove ads
Interactive-only features
Summarize
Perspective
Command History
Unlimited size command history.[50] This feature is available in interactive mode only.
Directory stack
A directory stack (pushd
and popd
built-ins) feature is available in interactive mode only.
Programmable completion
Also known as "tab completion" or "command-line completion", when a user presses the Tab ↹, within an interactive command-shell Bash automatically uses any available completion scripts to suggest partly typed program names, filenames and variable names.[51] [4] The Bash command-line completion system is very flexible and customizable, and is often packaged with functions that complete arguments and filenames for specific programs and tasks.
Bash supports programmable completion via built-in complete
, compopt
, and compgen
commands.[52]
The feature has been available since the beta version of 2.04 released in 2000.[53]
These commands enable complex and intelligent completion specification for commands (i.e., installed programs), functions, variables, and filenames.[54]
The complete
and compopt
two commands specify how arguments of some available commands or options are going to be listed in the readline input.As of version 5.1 completion of the command or the option is usually activated by the Tab keystroke after typing its name.[54]
This feature is available in interactive mode only.
Prompts
Configurable prompts. This feature is available in interactive mode only.
Restricted mode
Modern systems provide more secure ways to implement a restricted environment, such as jails, zones, or containers.[55]
A restricted shell is used to set up an environment more controlled than the standard shell. A restricted shell behaves identically to bash with the exception that numerous actions are disallowed or not performed, including:
- Changing directories with the
cd
builtin. - Setting or unsetting the values of the
$SHELL
,$PATH
,$HISTFILE
,$ENV
, or$BASH_ENV
variables. - Specifying command names containing slashes on the CLI.
- Using absolute pathnames as arguments to the
.
,history
, orhash -p
commands - Specifying a path search with
. -p
orcommand -p
- Importing function definitions and parsing the value of
$SHELLOPTS
from the shell environment at startup. - Redirecting output using the
>
,>
,<>
,>&
,&>
, and>>
redirection operators. - Using the
exec
builtin to replace the shell with another command. - Altering shell builtins
Once restricted mode is enabled, it cannot be disabled. These restrictions are enforced after any startup files are read, and it does not apply to shell scripts. Restricted mode is rarely used.
Remove ads
Documentation
Summarize
Perspective
User Manual
A user manual for Bash is provided by the GNU Project.
It is sometimes considered to be a more user-friendly document than the man page.
"You may also find information about Bash ...by looking at /usr/share/doc/bash
, /usr/local/share/doc/bash
, or similar directories on your system."[56]
On GNU/Linux systems, if the info program is available then the GNU Manual version relevant for your installation should also be available at info bash
.[57][58]
Man page
The most recent technical manual, or 'man page', is intended to be the authoritative explanatory technical document for the understanding of how bash operates.
On GNU/Linux systems, the version relevant for your installation is usually available through the man program at man bash
.[57][35][59]
help builtin
With recent versions of Bash, information on shell built-in commands can be found by executing help
, help [name of builtin]
or man builtins
at a terminal prompt where bash is installed.
The printf command can be invoked via env to ensure that you run the program found via your shell's search path, and not a shell alias or built-in function: env printf --help
.[60]
POSIX Specification
For the purpose of allowing inter-operability among different shell programs running on different operating systems, the POSIX Specification influences how modern UNIX-like shells are written. Bash "is intended to be a conformant implementation of the IEEE POSIX "Shell and Utilities" portion of the IEEE POSIX specification (IEEE Standard 1003.1)."[61] The most recent publication of the standard (2024) is available online.[62]
As the standard upon which bash is based, the POSIX Standard, or IEEE Std 1003.1,[63] et seq, is especially informative.
Further resources
"The project maintainer also has a Bash page which includes Frequently Asked Questions",[56][64][65] this FAQ is current as of bash version 5.1 and is no longer updated.
Informal avenues of support are available via IRC at libera.chat, in the #bash channel, and mailing lists are available at Bash - GNU Project - Free Software Foundation.
Remove ads
Security and vulnerabilities
Summarize
Perspective
Root scripts
Running any shell scripts as the root user has, for years, been widely criticized as poor security practice. One commonly given reason is that, when a script is executed as root, the negative effects of any bugs in a script would be magnified by root's elevated privileges.
One common example: a script contains the command, rm -rf ${dir}/
, but the variable $dir
is left undefined.
In Linux, if the script was executed by a regular user, the shell would attempt to execute the command rm -rf /
as a regular user, and the command would fail.
However, if the script was executed by the root user, then the command would likely succeed and the filesystem would be erased.
It is recommended to use sudo on a per-command basis instead.
Input validation
Command injection
Path traversal
TOCTOU errors (Race conditions)
Shellshock
In September 2014, a security bug was discovered[66] in the program. It was dubbed "Shellshock." Public disclosure quickly led to a range of attacks across the Internet.[67][68][69]
Exploitation of the vulnerability could enable arbitrary code execution in CGI scripts executable by certain versions of Bash. The bug involved how Bash passed function definitions to subshells through environment variables.[70] The bug had been present in the source code since August 1989 (version 1.03)[71] and was patched in September 2014 (version 4.3).
Patches to fix the bugs were made available soon after the bugs were identified. Upgrading to a current version is strongly advised.
It was assigned the Common Vulnerability identifiers CVE-2014-6271, CVE-2014-6277 and CVE-2014-7169, among others. Under CVSS Metrics 2.x and 3.x, the bug is regarded as "high" and "critical", respectively.
Remove ads
Deprecated syntax
- Backtick style command substitutions:
`...`
is deprecated in favor of$(...)
;
- Use of
-a
or-o
intest
/[
/[[
commands,- for example,
[ -r ./file -a ! -l ./file ]
is deprecated in favor of[ -r ./file ] && ! [ -l ./file ]
;
- for example,
- Use of the arithmetic syntax
$[...]
is deprecated in favor of$((...))
or((...))
, as appropriate;
- Use of
^
as a pipeline is deprecated in favor of|
; - Any uses of expr or let.
Remove ads
Debugging
Summarize
Perspective
Table of Features
- Shell features specified by POSIX:
- Bash features not specified by POSIX:
- Third party debugging utilities:
Examples
With the "${var:?}"
parameter expansion, an unset or null variable can halt a script.
$ cat ex.sh #!/bin/bash bar="foo is not defined" echo "${foo:?$bar}" echo this message doesn't print $ ./ex.sh ./ex.sh: line 3: foo: foo is not defined $
Reliably printing the contents of an array that contains spaces and newlines first in a portable syntax, and then the same thing in Bash.
Note that POSIX doesn't have named array, only the list of arguments, "$@"
, which can be re-set by the set builtin.
$ # In POSIX shell: $ set -- "a" " b" " > c " $ printf ',%s,\n' "$@" ,a, , b, , c,
Note that in Bash, the number of spaces before the newline is made clear.
$ # In Bash: $ array=( "a" " b" " > c " ) $ declare -p array declare -a array=([0]="a" [1]=" b" [2]=$' \n c ')
Printing an error message when there's a problem.
$ cat error.sh #!/bin/env bash if ! lsblk | grep sdb then echo Error, line "${LINENO}" fi $ ./error.sh Error, line 130
Using xtrace.
If errexit had been enabled, then echo quux
would not have been executed.
$ cat test.sh #!/bin/env bash set -x foo=bar; echo "${foo}" false echo quux $ ./test.sh + foo=bar + echo bar bar + false + echo quux quux
Note: $BASHPID
differs from $$
in certain circumstances, such as subshells that do not require bash to be reinitialized.
$ echo $(echo $BASHPID $$) $$ $BASHPID 25680 16920 16920 16920 # | | | | # | | | \-- $BASHPID outside of the subshell # | | \-- $$ outside of the subshell # | \-- $$ inside of the subshell # \-- $BASHPID inside of the subshell
Bug reporting
An external command called bashbug reports Bash shell bugs. When the command is invoked, it brings up the user's default editor with a form to fill in. The form is mailed to the Bash maintainers (or optionally to other email addresses).[101][102]
History
Summarize
Perspective
Shell script functionality originated with files called "runcoms" in reference to the 1963 macro processor of the same name. The suffix "rc" is short for "runcom."[103] The term "shell" was coined by Louis Pouzin in 1964 or 1965, and appeared in his 1965 paper, "The SHELL, A Global Tool for Calling and Chaining Procedures in the System,"which describes many features later found in many UNIX shells.[104][105] The ASCII standard for character encoding was defined in 1969 in a document called Request for Comments (RFC) 20. [106]
Timeline
See also
Summarize
Perspective
- Comparison of command shells
- Multics § Commands, exec_com: the first command processor.[140]
- FTP download from GNU Project of Bash versions 1.14.0 to current.[141]
Unix shells
- Almquist shell (ash)
- Bourne shell (sh)
- BusyBox
- C shell (csh)
- Debian-Almquist Shell (dash)
- Fish shell: Friendly Interactive Shell
- Google Shell (goosh) – a UNIX-like front-end for Google Search.
- Korn shell (ksh), of which there are numerous variations.
- nsh – "A command-line shell like fish, but POSIX compatible."[142]
- osh – "Oil Shell is a Bash-compatible UNIX command-line shell"; available on Arch.
- Mashey or Programmer's Workbench shell
- Qshell for IBM i
- rc from Plan 9
- RUNCOM
- rush – Restricted User Shell, available on Debian.[118]
- Stand-alone shell (sash)
- scsh – The Scheme Shell.
- TENEX C shell (tcsh)
- Thompson shell (tsh)
- Toybox
- yash – Yet Another Shell, aims "to be the most POSIX-compliant shell in the world"; available on Arch.
- Z shell (zsh)
Graphical interface to scripts
There are many programs that allow you to create a graphical interface for bash scripts.
- dialog - is a utility that allows you to create dialog boxes in the console, using the curses and ncurses libraries .
- whiptail - is an analogue of the dialog utility, it uses the newt library .
- zenity - is the most popular application for creating a graphical interface for scripts.
- kdialog - is a KDE equivalent of zenity .
- yad - is a fork of zenity, with more features.
- xdialog - is a replacement for dialog that is designed to give programs launched from the terminal an X Window System interface .
- gtkdialog - is the most functional utility for creating graphical applications on bash scripts.
Further reading
- Pouzin, Louis (2 April 1965). "The SHELL: A Global Tool for Calling and Chaining Procedures in the System" (PDF). mit.edu. Massachusetts Institute of Technology. Retrieved 8 August 2025.
- Stephenson, Neal (2003). In the Beginning... Was the Command Line. HarperCollins. ISBN 978-0380815937.
- M. Jones (9 December 2011). "Evolution of shells in Linux: From Bourne to Bash and beyond". ibm.com. IBM. Retrieved 8 August 2025.
{{cite web}}
: CS1 maint: url-status (link) - "Scripting Reference :: Scripting with the Bourne-Again Shell (Bash)". berkeley.edu. University of California, Berkeley. Retrieved 19 May 2024.
{{cite web}}
: CS1 maint: url-status (link) - "IRIS :: Instructional & Research Information Systems :: FAQ: Unix :: About UNIX Shells". berkeley.edu. University of California, Berkeley. Retrieved 8 August 2025.
{{cite web}}
: CS1 maint: url-status (link) - Newham, Cameron; Rosenblatt, Bill. "Learning the Bash Shell, 2e". oreilly.com. Retrieved 8 August 2025.
Content preview
{{cite web}}
: CS1 maint: url-status (link) - "Shell Scripting Primer". apple.com. Retrieved 8 August 2025.
Copyright © 2003, 2014 Apple Inc All Rights Reserved. ... Updated: 2014-03-10
{{cite web}}
: CS1 maint: url-status (link) - "Shell Style Guide". google.github.io. Retrieved 8 August 2025.
{{cite web}}
: CS1 maint: url-status (link)
Notes
- This description does not apply to Windows-based operating systems.
- Bash 4 also switches its license to GPL-3.0-or-later.[48]
References
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads