What is BASH
BASH is a shell (The name stands for Bourne Again Shell which refers to one of its predecessors, the Bourne Shell). A shell is the software which parses the commands and instructions that you enter at the prompt of your terminal or virtual console, then runs them on your behalf.
How does BASH know about commands, programs and utilities?
BASH determines the existence of commands you type by searching for them in your PATH
environment variable (more about this later). If you enter the command:
echo $PATH
or
printenv PATH
This will show you exactly what paths are searched for what's available on your system.
A default example of what PATH
holds might look like this:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
As you can see, each of the paths is delimited (separated) by a colon.
So with a PATH
variable like this one, when you run a command the first place the shell checks for the existence of the command is /usr/local/sbin
. If its not found there, then it checks /usr/local/bin
and so on.
You can add paths to your PATH
variable by editing ~/.profile
.
Find this line:
PATH="$HOME/bin:$PATH"
and add your extra path to the end of this string. For example /usr/extra/path
PATH="$HOME/bin:$PATH:/usr/extra/path"
New shells will now get the new PATH.
To pick up the new PATH
in your current shell, you'll then need to run:
source ~/.profile
There's more on the topic of configuring bash in the next section.
Note that if you do add your own changes to the PATH
variable, it's considered good practice not to put a .
(current directory) on the list of paths to search, especially if it's for root's PATH
. For users other than root, if you must put a .
in the path, put it last so that the normal command locations are searched before the current directory.
Configuring BASH
We cover this in more detail in BASH Configuration, but for now we'll just mention that the files ~/.profile
and ~/.bashrc
can be used to configure your shell. (The first is run at initial login, the second is run when a new instance of /bin/bash
is started).
Environment variables
Environment variables are one of the ways in which BASH and the programs that it runs for you are configured. To get a feel for what sort of variables exist, you can dump of all the environment variables by running:
printenv
We'll discuss environment variables that affect specific programs in their relevant posts. For now the main ones to know about are: PATH
(mentioned above) and PS1
which is used for customising the command prompt which we'll point you toward below.
Customising the command prompt
If you'd like to tweak the shell prompt displayed in your terminal, you'll need to change the PS1
environment variable.
For example, you may wish to include the date and time in the prompt.
In Ubuntu, the PS1
variable is set in your ~/.bashrc
file. To take a look at what it end up as, run:
echo \$PS1
You should see something like:
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$
So to add the date and time (without seconds - if you also want seconds, add :%S
after the %M
into the string below) to the current shell you need to add the sub string:
\D{%Y-%m-%d %H:%M}
To add it temporarily, that is without affecting future bash shell instances, you could run the following:
PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h: \D{%Y-%m-%d %H:%M}:\w\$ '
Note that using single quotes is important here otherwise the string you set will be interpreted by the shell before being set, thus setting a string other than what you intend!
To change it permanently, you need to add the substring to your PS1
variable in ~/.bashrc
file.
We'll cover customising this prompt and others in more detail in a future post.
External commands vs built-in commands
Some commands are build into BASH itself (that is they are part of BASH) and others are external commands. To find out whether a command is built in or not you can use type
, for example:
type pwd
Tells us that pwd
is built into bash, whereas:
type ls
tells us that ls is aliased to ls --color=auto
, while adding a -a
:
type -a ls
tells us that the underlying ls is an external command /bin/ls
.
Note that some commands will have a built-in and an external version of the command.
BASH keyboard shortcuts
To help you become more productive when using the command line, please refer to the list of bash shortcuts.
Introduction to standard input, output, and error
Linux sends all output to a file. Even the screen (where your shell prompt is) is considered a file.
Unless a program or command redirects output, it is sent to a special file called "standard output". By default, this represented by the screen.
Similarly, errors from a program are sent to "standard error" which by default is also represented by the screen.
The symbol &1
can be used to represent standard output, while &2
represents standard error.
There is also an &0
which represents standard input.
So you can consider &1
and &2
as locations where you can send data, while &0
is a location you can get data from.
As you'll see shortly, you can redirect standard input and output to places other than these and even make the data vanish if need be.
Storing command and program results to file
You can redirect data output from a command into a file by using the >
redirection operator.
For example to store the result of ls -la
into a file called out.txt
, you could use:
ls -la > out.txt
Note that if the file out.txt
does not exist, it will be created. If it does exist it will be overwritten (clobbered).
If you'd like to append the output from a command to a file if it already exists (rather that clobber the file), you can use the append redirection operator >>
, for example:
ls -la >> out.txt
Redirecting command output and errors to specific places
You can explicitly redirect output by using 1>
for example:
ls -la 1> output.txt
Similarly, you can redirect errors by using 2>
for example:
ls -la no_such_file.txt 2> error.txt
These can be combined so any errors get sent to one file while normal output gets send to another file. For example, this command will find all files with the extension .conf
that live under the /etc
directory, putting any errors into error.txt
while putting normal output (the results) into results.txt
:
find /etc/ -name "\*.conf" 2>error.txt 1>result.txt
If you need to append to the files rather than replace them for each run, you could use:
some_command 2>>error.txt 1>>result.txt
where some_command can be replaced by whatever command you need to run. To send both standard output and error to the same file, you can use one of >&
or &>
, for example:
find /etc/ -name "\*.conf" &> output.txt
alternative (perhaps more readable) option:
find /etc/ -name "\*.conf" > output.txt 2>&1
where we basically just redirect standard output using >
, and then send errors to the location of standard output (remember &1
mentioned earlier?) which we've set to be output.txt
.
Redirecting command output to other commands
When you would like to send the output from one command to the input of another, you can use the pipe operator |
. For example, to count the number of lines in a file called file.txt
, you could use:
cat file.txt | wc -l
You can pipe many commands together, for example running this contrived example:
cat file.txt | tail -n 100 | less
will pass the last 100 lines from the file file.txt
to the less command so you can easily scroll up and down the resulting lines.
Redirecting output and/or errors to nowhere
You can send any sort of data to the special file /dev/null
, which is like a black hole, so the data ends up disappearing forever.
If there's a command that produces output or errors that you're not interested in seeing, just send the data to /dev/null
and it will not get displayed anywhere. For example, to send error messages to /dev/null
, use:
some_command 2> /dev/null
(where some_command is whatever command you need to run).
Directing output to more than one place
If you need to display or save output to file and also send that output to another command at the same time, you can use the tee
command.
For example the below line will save the output from some_command
into save.txt
, while still sending the output to grep
to search for lines containing "something", then counting the number of lines found:
some_command | tee save.txt | grep "something" | wc -l
Hidden files
Had you noticed that doing an ls
on your home directory doesn't show any files that begin with a dot such as .bashrc
or .profile
?
This is because such files are hidden by default. They are normally some sort of configuration file, so are kept out of the results shown by ls unless you use the -a
or --all
option. Hence running:
ls -la
will show such files.
Note that using hidden files such as these are just to help keep your directories free from clutter and are nothing to do with security!
BASH scripting
Putting one or more commands that perform a specific job/task into a file for future use is pretty common.
Such a file can be referred to as a bash script, and would have the extension .sh
, so myjob.sh
could be an example of what you might call such a script.
Bash also provides looping and control structures for your use, much in the same way as a conventional programming language. Hence bash scripting can be considered as being in the category of programming.
BASH scripting is beyond the scope of this post, but we shall be covering the topic at some stage in the future.
Thanks to Brian Fox and Chet Ramey for implementing BASH.