Bash
From Wikipedia, the free encyclopedia
GNU Bourne-Again Shell | |
![]() Screenshot of a sample bash session |
|
Developer: | Chet Ramey |
---|---|
Latest release: | 3.2.9 / December 12, 2006 |
OS: | Various |
Use: | Unix shell |
License: | GNU General Public License |
Website: | Official website |
Bash is a Unix shell written for the GNU Project. The name of the actual executable is bash. Its name is an acronym for Bourne-again shell, a pun ('Bourne again' / 'born again') on the name of the Bourne shell (sh), an early and important Unix shell written by Stephen Bourne and distributed with Version 7 Unix circa 1978. Bash was created in 1987 by Brian Fox. In 1990 Chet Ramey became the primary maintainer.
Bash is the default shell on most Linux systems as well as on Mac OS X and it can be run on most Unix-like operating systems. It has also been ported to Microsoft Windows within the Cygwin POSIX emulation environment for Windows, to MS-DOS by the DJGPP project and to Novell NetWare. Released under the GNU General Public License, Bash is free software.
Contents |
[edit] Syntax
Bash's command syntax is a superset of Bourne shell command syntax. The vast majority of Bourne shell scripts can be executed by Bash without modification, with the exception of Bourne shell scripts referencing a Bourne special variable or those using builtin Bourne commands. Bash command syntax includes ideas drawn from the Korn shell (ksh) and the C shell (csh) such as command line editing, command history, the directory stack, the $RANDOM and $PPID variables, and POSIX command substitution syntax: $(...). When used as an interactive command shell and pressing the TAB key, Bash automatically completes partly typed program names, filenames, variable names, etc.
Bash's syntax has many extensions the Bourne shell lacks. Several are enumerated here.
[edit] Integer mathematics
Bash can perform integer calculations without spawning external processes, unlike the Bourne shell. Bash uses the ((...)) command and the $[...] variable syntax for this purpose.
VAR=55 # Assign integer 55 to variable VAR. ((VAR = VAR + 1)) # Add one to variable VAR. Note the absence of the '$' character. ((++VAR)) # Another way to add one to VAR. Performs C-style pre-increment. ((VAR++)) # Another way to add one to VAR. Performs C-style post-increment. echo $[VAR * 22] # Multiply VAR by 22 and substitute the result into the command. echo $((VAR * 22)) # Another way to do the above.
The ((...)) command can also be used in conditional statements because its exit status is zero or nonzero (most times 1) depending on whether the condition is true or false.
if ((VAR == Y * 3 + X * 2)) then echo Yes fi
((Z > 23)) && echo Yes
The ((...)) command supports the following relational operators: '==', '!=', '>', '<', '>=', and '<='.
Bash cannot perform in process floating point calculations. The only Unix command shells currently capable of this are the Korn Shell and the Z shell.
[edit] Integer comparison
While not Bash specific it is still very relevant.
-eq Equal to -ne Not equal to -gt Greater than -ge Greater than or equal to -lt Lesser than -le Lesser than or equal to < Lesser than (special ((...)) construct applies) > Greater than <= Lesser than or equal to >= Greater than or equal to
Examples
n1=34 n2=43 # if [ "$n1" -eq "$n2" ]; then # Normal operation if (("$n1" < "$n2")); then # Special construct to use with <, >, <=, and >=.
[edit] String comparison
While not Bash specific this is as relevant for Bash as any other shell.
Operators
== String1 is equal to String2 (same as single = on some systems) != String1 is not equal to String2 < String1 is lesser than String2 in ASCII value (see example for correct quoting) > String1 is greater than String2 in ASCII value (see example for correct quoting) -z String is empty / zero length -n String is not null / empty
Examples
s1="Test" s2="String" # if [ $s1 == $s2 ]; then # This is the base form, but things may go wrong. if [ "$s1" == "$s2" ]; then # This takes care of spaces in the strings - but still room for improvement. if [ "x$s1" == "x$s2" ]; then # By prepending with "x" it will also handle empty strings and not fail because of that.
Be aware of escaping < and > when shell scripting
if [[ "x$s1" < "x$s2" ]]; then # Use double brackets to avoid escaping < and >. if [ "x$s1" \< "x$s2" ]; then # Or simply escape it to treat is as the special (redirect) character it is.
[edit] File tests
While this is not Bash specific it is definitely relevant to this article.
Regular tests
-d Directory -e Exists (same as -a on some systems) -f Regular file -h Symbolic link (same as -L on some systems) -p Named pipe -r Readable -s Not zerosize -S Socket -w Writable -N Modified since last read
Comparing tests
-nt File1 newer than File2 -ot File1 older than File2 -ef File1 is a hard link to File2
Examples
if [ -e /tmp/file ]; then echo "File exists." else echo "File does not exist!" fi
if [ /tmp/file1 -nt /tmp/file2 ]; then echo "File1 is newer than file2." else echo "File1 is older than file2." fi
[edit] I/O redirection
Bash has several I/O redirection syntaxes that the traditional Bourne shell lacks. Bash can redirect standard output and standard error at the same time using the following syntax.
command &> file
This is simpler to type than the Bourne shell equivalent 'command > file 2>&1'. Since version 2.05b Bash can redirect standard input from a string using the following syntax.
command <<< "string to be read as standard input"
If the string contains whitespace, it must of course be quoted or the white space escaped.
Example: Redirect standard output to a file, write data, close file, reset stdout
# make Filedescriptor(FD) 6 a copy of stdout (FD 1) exec 6>&1 # open file "test.data" for writing exec 1>test.data # produce some content echo "data:data:data" # close file "test.data" exec 1>&- # make stdout a copy of FD 6 (reset stdout) exec 1>&6 # close FD6 exec 6>&-
Open and close files
# open file test.data for reading exec 6<test.data # read until end of file while read -u 6 dta do echo "$dta" done # close file test.data exec 6<&-
Catch output of external commands
# execute 'find' and store results in VAR # search for filenames which end with the letter "h" VAR=$(find . -name "*h")
Bash also supports here documents.
[edit] In-process regular expressions
Bash 3.0 supports in-process regular expression matching using the following syntax, reminiscent of Perl:
[[ string =~ regex ]]
The regular expression syntax is the same as that documented by the regex(7)[1] man page. The exit status of the above command is 0 if the regex matches the string, 1 if it does not match. Parenthesized subexpressions in the regular expression can be accessed using the shell variable BASH_REMATCH, as follows:
if [[ abcfoobarbletch =~ 'foo(bar)bl(.*)' ]] then echo The regex matches\! echo $BASH_REMATCH -- outputs: foobarbletch echo ${BASH_REMATCH[1]} -- outputs: bar echo ${BASH_REMATCH[2]} -- outputs: etch fi
As of Bash 3.2, the above code does not work - the regular expression begins with the first non-whitespace character after =~. So the above code would become:
if [[ abcfoobarbletch =~ foo(bar)bl(.*) ]] then echo The regex matches\! echo $BASH_REMATCH -- outputs: foobarbletch echo ${BASH_REMATCH[1]} -- outputs: bar echo ${BASH_REMATCH[2]} -- outputs: etch fi
This syntax gives performance superior to spawning a separate process to run a grep command, because the regular expression matching takes place within the Bash process. The advantage grep gives is that it allows the programmer to explicitly specify the style of regular expression that will be used (i.e. Perl, POSIX, etc) allowing programmers to write the regular expressions in the style they are most familiar with. However, the difficulty this imposes is that subexpressions in grep can only be used as back-references in the same expression - thus it is not possible to extract subexpressions to be used outside of the instance of grep that matched it.
If the regular expression or the string contain whitespace or shell metacharacters (such as '*' or '?'), they should be quoted (again, this is only for versions of Bash supporting regular expressions but below version 3.2).
[edit] Backslash escapes
Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the C programming language. Backslash escape sequences, if present, are decoded as follows:
Backslash escape |
Expands to ... |
---|---|
\a | An alert (bell) character |
\b | A backspace character |
\e | An escape character |
\f | A form feed character |
\n | A new line character |
\r | A carriage return character |
\t | A horizontal tab character |
\v | A vertical tab character |
\\ | A backslash character |
\' | A single quote character |
\nnn | The eight-bit character whose value is the octal value nnn (one to three digits) |
\xHH | The eight-bit character whose value is the hexadecimal value HH (one or two hex digits) |
\cx | A control-X character |
The expanded result is single-quoted, as if the dollar sign had not been present.
A double-quoted string preceded by a dollar sign ($"...") will cause the string to be translated according to the current locale. If the current locale is C or POSIX, the dollar sign is ignored. If the string is translated and replaced, the replacement is double-quoted.
[edit] Startup scripts
When Bash starts, it executes the commands in a variety of different scripts.
When Bash is invoked as an interactive login shell, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. One can force this behavior for a non-interactive shell with the --login option. The --noprofile option may be used to inhibit this behavior.
When a login shell exits, Bash reads and executes commands from the file ~/.bash_logout, if it exists.
When an interactive shell that is not a login shell is started, Bash reads and executes commands from ~/.bashrc, if that file exists. This may be inhibited by using the --norc option. The --rcfile file option will force Bash to read and execute commands from file instead of ~/.bashrc.
When Bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following command were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search for the file name.
If Bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well. When invoked as an interactive login shell, or a non-interactive shell with the --login option, it first attempts to read and execute commands from /etc/profile and ~/.profile, in that order. The --noprofile option may be used to inhibit this behavior. When invoked as an interactive shell with the name sh, Bash looks for the variable ENV, expands its value if it is defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked as sh does not attempt to read and execute commands from any other startup files, the --rcfile option has no effect. A non-interactive shell invoked with the name sh does not attempt to read any other startup files. When invoked as sh, Bash enters POSIX mode after the startup files are read.
When Bash is started in POSIX mode, as with the --posix command line option, it follows the POSIX standard for startup files. In this mode, interactive shells expand the ENV variable and commands are read and executed from the file whose name is the expanded value. No other startup files are read.
Bash attempts to determine when it is being run by the remote shell daemon, usually rshd. If Bash determines it is being run by rshd, it reads and executes commands from ~/.bashrc, if that file exists and is readable. It will not do this if invoked as sh. The --norc option may be used to inhibit this behavior, and the --rcfile option may be used to force another file to be read, but rshd does not generally invoke the shell with those options or allow them to be specified.
[edit] External links
- GNU Bash -(GNU project page)
- Author's Bash page
- bashdb, a gdb-style debugger
- Bash Guide for Beginners, from the Linux Documentation Project
- Advanced Bash Scripting Guide
- Bash tutorial(GNULamp)
- Greycat's Bash FAQ
- Greycat's Bash Pitfalls
- Bash shell scripts sorted by category
History: GNU Manifesto • GNU Project • Free Software Foundation (FSF)
GNU licenses: GNU General Public License (GPL) • GNU Lesser General Public License (LGPL) • GNU Free Documentation License (FDL)
Software: GNU operating system • bash • GNU Compiler Collection • Emacs • GNU C Library • Coreutils • GNU build system • other GNU packages and programs
Speakers: Robert J. Chassell • Loïc Dachary • Ricardo Galli • Georg C. F. Greve • Federico Heinz • Bradley M. Kuhn • Eben Moglen • Richard Stallman • Len Tower