Top Qs
Timeline
Chat
Perspective

Bash (Unix shell)

GNU replacement for the Bourne shell From Wikipedia, the free encyclopedia

Bash (Unix shell)
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] It is available on nearly all modern operating systems, making it a versatile tool in various computing environments.

Quick Facts Original author(s), Developer(s) ...

Created in 1989 by Brian Fox for the GNU Project, it is supported by the Free Software Foundation.[9] It holds historical significance as one of the earliest programs ported to Linux by Linus Torvalds, alongside the GNU Compiler (GCC).[10]

As a command-line interface (CLI), Bash (short for "Bourne Again SHell") operates within a terminal emulator, or text window, where users input commands to execute various tasks.[11][12] It also supports the execution of commands from files, known as shell scripts, facilitating automation.

While in POSIX-mode, Bash complies with most of the requirements of the POSIX standard for Unix shells and utilities. As a result, Bash can execute the vast majority of Bourne shell scripts without modification.

The Bash command syntax is a superset of the Bourne shell sh command syntax, from which all basic features of the language were copied. Some other ideas were borrowed by the C shell, csh and the Korn Shell, ksh.

Remove ads

Features: Info 1

Summarize
Perspective

ASCII, strings and numbers

All input and output at the commandline is communicated using printable, human-language characters, such as the letter a or the number 1. One of the earliest devised and widespread ways of encoding these characters in a consistent manner which computers could understand was a system called ASCII. It was defined in 1969 in a document called Request for Comments (RFC) 20.[13] 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: <>

All printable and non-printing characters are converted to and from a binary number representation according to the ASCII standard.

Any series of characters is called a "string." In Unix-like operating systems, all characters, printable and non-printing, except for a few including the null character and forward slash /, can be used in naming files. In Bash, variables can be identified as numbers, or "assigned the attribute of integer," however, at the level of data processing Bash handles all data as strings. The Bash binary does not provide floating-point arithmetic functionality.

CLI and GUI

From 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 that could only display textual characters. In time, computer monitors were developed, although display of graphics was not yet possible. In the 1970's, these interfaces were known as hardware video terminals, and their interaction paradigm is the basis of what we consider the command-line interface (CLI). A well known example is the VT100 by the Digital Equipment Corporation (DEC).

As computing capabilities progressed, it became possible for computers to draw graphics on the screen. New graphical user interfaces (GUI's) were designed with these capabilities in mind. It became no longer necessary to use monitors which were only capable of drawing textual characters, however, the CLI remains a powerful means for utilizing a machine.

Terminal emulators are GUI software programs which create a visual representation of these earlier hardware computer terminals. Exapmles of terminal emulators available in GNU/Linux include xterm, GNOME terminal and Konsole.

Today, when a human user initiates a login session, that procedure usually occurs via some graphical user interface.

Readline

The way in which Bash accepts control codes from user input is configurable. By default, the keypress combinations in Bash mirror those of the Emacs text editing software.[14] Vi (text editor) keybindings are also available and can be enabled by running set -o vi.[15][16] This functionality is provided by a separate program called GNU Readline which is sometimes taken to be a part of the Bash shell itself. In most Unix-like distributions (Fedora, Debian, openSuse, OpenBSD, etc.) it is packaged and disributed with the Bash binary. Default keybindings for control codes entered at the keyboard commonly seen when using Bash include:

  • Ctrl+ c - Cancels the current command
  • 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+ right-arrow - Move the cursor one word to the right
  • Ctrl+ left-arrow - Move the cursor one word to the left

This feature is available in interactive mode only.

Comments

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. These are Bourne comments and they will not print in xtrace.

A less commonly known comment style are Thompson comments, denoted with a colon character: :. In Bash the colon character is a shell builtin which serves as a "null command." Any arguments to the colon : builtin are ignored and the command always returns true. The : builtin is specified by POSIX. [17]

Thompson comments will print in xtrace, and any values assigned to parameters, as arguments to the : builtin, will have been expanded.

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 are identified and described using a specific list of attributes. A process identifier, denoted in Bash by the variables dollar $$, $BASHPID and $PPID, is an integer between 300 and approximately 2^24, depending on the OS. In Linux, when the highest PID is reached, the numbering system restarts at 300. Most processes have a current working directory (CWD) attribute, denoted in Bash by the variable $PWD. A common command for identifying the CWD of a shell process is the pwd command (short for "print working directory").

Each process has attributes which identify its owner and group memberships. The most commonly seen of these are the user and group ID's, $UID and $GID, and the effective user and group ID's, $EUID and $EGID,

Files and permissions

In Unix-like operating systems, all objects locatable on the file system are considered to be "files." (This description does not apply to Windows-based operating systems.) 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. Each of these "files" also has attributes which identify its owner and group memberships.

All "files" have a set of file-system permissions which control how processes may interact with the file. A process may have read, write or execute permissions on a file. 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.

Paths

In Unix-like OS's, files, hardlinks, device nodes, etc., (i.e., "files") are sorted into directories that form a heirarchical file structure which is nested in a "parent" and "child" manner. The base of the heirarchy is called the "root directory" which is denoted by one forward slash: /.

On the commandline, a file can be identified using its full filename or an abbreviated filename. A full filename is called an "absolute path;" the left side of the string always begins at with a forward slash: /etc or /home/liveuser/.bashrc. On the commandline, as shorthand the current working directory (CWD) can be referred to as ., and its parent directory as ... (The shell builtin ., synonymous with the source builtin, is something else.) These shorthand identifiers are called "relative paths." When the kernel searches for a directory indicated by the string ../../../bin/ls the starting point for the search is the leftmost directory, in this case a directory relative to the current working directory (CWD): ... Specifying a directory in this way requires the kernel to traverse the filesystem through abstractly defined filenames. This process is called "path traversal." For absolute paths, the leftmost directory is known positively: it's the filesystem root directory, /. 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.

A "canonicalized path" is an absolute path for which all of its constituent directories are neither hardlinks nor symlinks. Canonicalized paths are produced as the output of realpath -e DIR, which is a POSIX-compliant command.

Execution

"Execution" of a given program occurs when an user (or some other program) asks the operating system to act upon the instructions contained in the given program.

When Bash looks for a command to execute, the directories it searches are those listed in the $PATH variable and the current working directory.

Bash reads commands one line at a time. If a command extends beyond the width of the terminal emulator, it's usually possible to keep typing and the command will wrap around. By default, Bash interprets any newline as the end of the current command. A newline is denoted by pressing Enter at the interactive command-line (CLI), by a literal newline in a script, or by a newline control character: $'\n'. To extend a command beyond one line onto a second line, it's necessary that the final character of the first line be an unescaped backslash, \, which signals "line continuation."

In certain circumstances, flow control constructs, etc., an interactive shell will sometimes automatically require line continuation so that a user can finish typing in a flow control construct.

By default, Bash executes commands in sequence. Commands on the CLI can be separated by a newline, or a semi-colon character ;. Bash always finishes parsing and executing one full command before moving on to and beginning with the parsing of the next command.

$ foo=aa bar=bb quux=cc zork=dd
$ set -o xtrace
$ : "${foo}"; : "${bar}"
+ : aa
+ : bb
$ : "${quux}" \
> : "${zork}"
+ : cc : dd
$

Data and code

In any computer system, it can be said that there two kinds of information: "data" and "code." An example of data would be a text file containing a list of phone numbers. An example of code, in the context of the shell, would be one or more commands that in some way perform operations upon external data. Data that regular users cannot ever access is said to be located in kernel space.

$ type -P grep # Code
/usr/bin/grep
$ vim ./phone-numbers.txt # Data
$ grep -e alison ./phone-numbers.txt # Code operating upon data
alison (555) 123-4567

Users

In Unix-like OS's, there are two kinds of users: "privileged," and "unprivileged" or "regular" users. A user account can be created for either a human or a programmatic user. A privileged user, often known as the "superuser" or "root," is allowed to do anything whatsoever on the machine. The operating system kernel is a privileged process. Unprivileged users are limited in various ways in what information they can access, read and in which programs they are allowed to execute.

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, non-privileged users a common default value for $PS1 is the dollar character, $ (not to be confused with the shell variable $$). 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

Features: Modes

Summarize
Perspective

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. Such functionality originated with files called "runcoms" in reference to the 1963 macro processor of the same name.[18] When executed as a standalone command at the command-line interface (CLI), by default Bash opens a new shell in interactive mode and the $SHLVL (ie, "shell level") parameter is increased, or "incremented," by one.

$ bash
$ declare -p SHLVL
2
$ sudo --login --user root
#

Login and non-login shells

Bash can also be executed as a login shell, or "session leader," in either interactive or non-interactive modes with the --login option. "Logging in" requires user authentication, and so only one login shell exists per user session. In GNU/Linux, a user's login shell is identified in the /etc/passwd file and valid system login shells are listed in the /etc/shells file. One means of altering a login shell is with the system command chsh.

$ 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. When a shell process begins, by default it reads certain configuration files known as "dotfiles." In Bash, login shells read a somewhat different set of dotfiles than do non-login shells. 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.

Non-interactive: 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 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
$

Non-interactive: the `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." By default, the shell reads a certain number of configuration files at startup such as /etc/profile and ~/.bashrc. By conventions, in Unix file names which begin with a "dot" are considered "hidden files."

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 intitialization of an interactive shell, Bash can be executed as either sh, bash --posix or bash -o posix.[19] To cause a script to be intialized 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.

The full list of features available in Bash which are not specified by POSIX is considerable. 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 . (ie, 'dot') builtin is POSIX, however
      • The source builtin is not POSIX
  • The $EPOCHSECONDS and $EPOCHREALTIME shell variables are not POSIX[20]

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.[19][21]

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.[22] Vidar Holen's shellcheck is another static linter written in Haskell which can parse script syntax for compatability with any or all of bash, dash, ksh, and Bourne sh.[23] 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),[21] while a script intending to support pre-POSIX Bourne shells, like autoconf's configure, are even more limited in the features they can use.[24]

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."[25]

Remove ads

Features: Info 2

Summarize
Perspective

xtrace

When xtrace is enabled, simple debugging content is printed to the terminal. xtrace is specified by POSIX and is Bash's most useful native debugging feature.

$ set -x
$ echo $((  2 + 2  ))
+ echo 4
4
$ set -- 1 2 3
$ printf '<%s>\n' "#@"
+ printf '<%s>\n' 1 2 3
<1>
<2>
<3>
$

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, (ie, 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 (0) 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 (1) and "false" is zero (0). 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 (1). If the statement evaluates to any number other than zero the arithmetic statement is "false" and the exit code is zero (0).

Not all Linux/UNIX commands provide meaningful exit codes beyond zero (0) and one (1), and there is no standard system for definitions of exit codes in Linux.

$ true; echo "$?"
0 # Exit code means "true"
$ false; echo "$?"; echo
1 # Exit code means "false"

$ bash -c 'exit 99'; printf 'exit-code: %d\n\n' "$?"
exit-code: 99

$ ((  1 - 1  )); printf '%d\n' "$?"
1 # This exit code means "true"
$ ((  1 + 1  )); printf '%d\n' "$?"
0 # ...and this exit code means "false"

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.[26] 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:

kill %1

Unicode

Support for Unicode in echo -e and ANSI-C quoting.

Regular Expressions

Bash 3.0 supports in-process regular expression matching using a syntax reminiscent of Perl.[27] Regexp matching is limited to strings on the right side of the =~ operator in the [[..]] extended test construct.[28]

$ [[ $line =~ [[:space:]]*(a)?b ]]

"That means values for line like ‘aab’, ‘ aaaaaab’, ‘xaby’, and ‘ ab’ will all match, as will a line containing a ‘b’ anywhere in its value."

IPC Signals

Signaling is a means of inter-process communication. Bash utilizes the trap builtin to catch and process signals.[29]

Remove ads

Features: Programming structures 1

Summarize
Perspective

Flow control

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).

  • if...fi compound commands; concept drawn from ALGOL68;[30]
  • case...esac compound commands; concept drawn from ALGOL68;[30]

For all commands the exit status is stored in the special variable $?. Bash also supports if...fi and case...esac forms of conditional command evaluation.

    • 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;
  • 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:
    • ((...)) numeric evaluation and testing; this includes almost all "C" language operators for arithmetic and numeric comparison;

Pipelines

Subshells

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:[31]
      • cd, pwd, etc.
    • set[32]
      • 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 command set -.
      • 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 a set -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.[33]
      • Both xtrace and verbose can be turned off at the same time with the command set -.
    • shopt[34]
      • expand-aliases: On by default in interactive shells. Some developers discourage its use in scripts.
Remove ads

Features: Data manipulations

Summarize
Perspective

Word Splitting

Quoting

according to quoting rules,

  • Including 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.[35] 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

Indexed arrays of unlimited size,

  • Arrays, Associative

Associative arrays via declare -A, and

In February 2009,[36] Bash 4.0 introduced support for associative arrays.[4] Associative array indices are strings, in a manner similar to AWK or Tcl.[37] They can be used to emulate multidimensional arrays. Bash 4 also switches its license to GPL-3.0-or-later.[38]

  • "Parameter Expansion"

Expansion syntaxes which can perform some tasks more quickly than external utilities, including, among others:

  • Pattern Substitution
    • ${foo//x/y} for sed 's/x/y/g',
  • Remove Matching Prefix or Suffix Pattern
    • ${bar##[a-zA-Z0-9]*} for cut -c8-,
  • Enumerate Array Keys
    • ${!array[@]}, and
  • Display Error if Null or Unset
    • ${var:?error message},

Pathname expansion

  • (Step 5) Pathname expansion, i.e., shell-style globbing and pattern matching using *, ?, [...], and
    • (Although they can be used in conjunction, the use of brackets in pattern matching, [...], and the use of brackets in the testing commands, [ and [[ ... ]], are each one different things.)

Locales

Remove ads

Features: Programming structures 2

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

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 lookup

(Shell scripts do not require compilation before execution and, when certain requirements are met, can be invoked as commands by using their filename.)

  • The resulting string is executed as a command.

Environment

  • Configurable execution environment(s):[39]
    • Shell and session startup files such as ~/.bashrc and ~/.profile (i.e., dotfiles); the suffix "rc" is short for "runcom;"[18]
    • 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.[40] 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

Features: The Parser

Summarize
Perspective
  • 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 $'...';
    • 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} for sed 's/x/y/g',
            • Remove Matching Prefix or Suffix Pattern
              • ${bar##[a-zA-Z0-9]*} for cut -c8-,
            • Enumerate Array Keys
              • ${!array[@]}, and
            • Display Error if Null or Unset
              • ${var:?error message},
        • Command substitution: $(...),
        • Process substitution, <() or >(), when a system supports it:
        • Arithmetic expansion, ((...)) or $((...)), including
      • (Step 4) Word splitting (again),
      • (Step 5) Pathname expansion, i.e., shell-style globbing and pattern matching using *, ?, [...], and
        • (Although they can be used in conjunction, the use of brackets in pattern matching, [...], and the use of brackets in the testing commands, [ and [[ ... ]], are each one different things.)
      • Quote removal;
    • 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;
    • Command name lookup is performed, in the following order:

(Shell scripts do not require compilation before execution and, when certain requirements are met, can be invoked as commands by using their filename.)

    • The resulting string is executed as a command.
Remove ads

Features: Info 3

Command History

Unlimited size command history.[41] This feature is available in interactive mode only.

Directory stack

A directory stack (see pushd and popd built-ins). This feature is available in interactive mode only.

Programmable completion

Also known as "tab completion" or "command-line completion", when a user presses the tab key, Tab, within an interactive command-shell Bash automatically uses any available completion scripts to suggest partly typed program names, filenames and variable names.[42] [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.[43] The feature has been available since the beta version of 2.04 released in 2000.[44] These commands enable complex and intelligent completion specification for commands (i.e., installed programs), functions, variables, and filenames.[45]

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.[45] This feature is available in interactive mode only.

Prompts

Configurable prompts. This feature is available in interactive mode only.

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."[46] 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.[47]

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.[48] On GNU/Linux systems, the version relevant for your installation is usually available through the man program at man bash.[49][50][51]

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.

Some commands, such as echo, false, kill, printf, test or true, depending on your system and on your locally installed version of bash, can refer to either a shell built-in or a system binary executable file. When one of these command name collisions occurs, bash will by default execute a given command line using the shell built-in. Specifying a binary executable's absolute path (i.e., /bin/printf) is one way of ensuring that the shell uses a system binary. This name collision issue also effects any "help summaries" viewed with kill --help and /bin/kill --help. Shell built-ins and system binary executable files of the same name often have differing options.

A brief summary of which options bash accepts on the commandline is available by running bash --help.

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)."[52] The most recent publication of the standard (2024) is available online.[53]

As the standard upon which bash is based, the POSIX Standard, or IEEE Std 1003.1,[54] et seq, is especially informative.

Further resources

"The project maintainer also has a Bash page which includes Frequently Asked Questions",[46][55] 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[56] in the program. It was dubbed "Shellshock." Public disclosure quickly led to a range of attacks across the Internet.[57][58][59]

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.[60] The bug had been present in the source code since August 1989 (version 1.03)[61] 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.

Deprecated syntax

  • Back-tick style command substitutions: `...` is deprecated in favor of
    • $(...);
  • Use of -a or -o in test/[/[[ commands,
    • for example, [ -r ./file -a ! -l ./file ] is deprecated in favor of
      • [ -r ./file ] && ! [ -l ./file ];
  • 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

More information Feature, POSIX 2024 ...
  • Shell features specified by POSIX:
    • Parameter Expansions:[76]
    • Special Parameters:[77][78]
    • Special Built-In Utility set:[79][80]
    • Special Built-In Utility trap:[80][81]
      • POSIX does specify certain uses of the trap builtin: ...
    • Utility printf: a means of reliably printing the contents of a variable:
  • Bash features not specified by POSIX:
    • Bash Variables:[82][83]
    • Shell Builtin set:[79][80]
    • Shell Builtin shopt:[84][80]
    • Shell Builtin trap:[81][80]
      • While POSIX does specify certain uses of the trap builtin, the following signal specs are Bash extensions: ...
  • Third party debugging utilities:
    • ShellCheck: Shell script analysis tool;[85][23]
    • devscripts-checkbashisms: Check whether a /bin/sh script contains any common bash-specific constructs;[86][22]
    • kcov: Code coverage tool without special compilation options;[87]
    • Bashdb: The Bash symbolic debugger.[88][89]

Examples

With the "${var:?}" parameter expansion, an unset or null variable can halt a script.

  • 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).[90][91]

Remove ads

History

Summarize
Perspective

While Bash was developed for UNIX and UNIX-like operating systems, such as GNU/Linux, it is also available on Android, macOS, Windows, and numerous other current and historical operating systems.[92] "Although there have been attempts to create specialized shells, the Bourne shell derivatives continue to be the primary shells in use."[93]

The term "shell" was coined by Louis Pouzin in 1964 or 1965,[94] and appeared in his 1965 paper, "The SHELL, A Global Tool for Calling and Chaining Procedures in the System."[95] This paper describes many features later found in Bash.

Timeline

More information Date, Event ...

See also

Summarize
Perspective

Unix shells

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

References

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads