The BASH Shell

30 November -0001
October 28, 2002

Once you have your Linux system set up you will get your first experience with the Linux shell. The shell is a command-line interface (CLI) to your kernel and hardware. The shell provides a method by which you can communicate to your computer through the keyboard. The shell takes keyboard input, translates it and passes it to the Linux kernel, and then recieves kernel responses, translates and displays them on your screen. All of this will happen behind the scenes and will be invisible to the user. The kernel, or the core of your operating system, requires a shell layer to translate keyboard input into understandable language and format kernel output for screen display. There are a huge number of shells available, but BASH is the most common and will likely be the shell you will see when you log in. Most modern linux distributions will automatically load a graphical user interface (GUI) over the shell as soon as you boot into your system and you may have to search for the shell or terminal icon in order to experience the shell. While you may be tempted to pass over the shell because of pre-conceived notions about the power of a CLI based on your Windows experience. whereas with a Microsoft Windows system the CLI is mainly used for debugging or maintenance and has none of the power of GUI management tools, the Linux system encapsulates all its power in the CLI. Many of the Linux GUI programs available to users are simply front ends that issue shell commands based on button clicks and other program options. In order to utilize the full potential of your Linux system you need to become familiar with the shell. Before we begin that discussion though, it is important to examine the myriad of different shells availabe. Some of the most common are:

sh- Bourne Shell, written by Steve Bourne at AT&T, this is one of the oldest shells in the Unix/Linux world. As a Unix based operating system, Linux has inheirited the Bourne Shell. On most Linux systems this shell won't actually be the original Bourne Shell, but a modern variant that is backwards compatible with the Bourne Shell.

bash- The bash shell was pioneered by the Free Software Foundations GNU project ( Bash is the Bourne Again Shell. While not entirely POSIX compliant, it is the defacto Linux shell.

ash- The A Shell, or ash, by Kenneth Almquist of Berkely is a lightweight Bourne Shell clone which you may find suitable for use on machines that are very tight on memory.1 Resembles the shell used in AT&T System V Unix.

bsh- (actually just a different name for ash)

POSIX-Standards comittees worked over the Korn shell and slightly modified some specifications to define a "standard" shell which systems meeting the POSIX spec. must comply with. On some systems, /bin/sh is actually now a POSIX compliant shell, fully compatible with Bourne shell, but with most of the ksh features. This standard was created partly because the early ksh was not fully 100% backward compatible with sh, and so caused trouble if it simply replaced it.2

csh- The C Shell, written by William Joy at Berkeley (the founder of Sun Microsystems). The C Shell was designed to be a programmers shell providing tools and options useful for programmers. One of the first shells to explore command line history, the C Shell didn't live up to intended potential and has largely fallen out of favor.

ksh- The Korn Shell, written by David Korn of AT&T, was a successful attempt to provide the functionality of C Shell while using a Bourne Shell syntax and maintaining Bourne Shell backward compatibility.

In order to experience the shell you're going to have to either launch a terminal session from an X windows session, or if your system logs you in without starting X then all you have to do is log in. Your shell session will start with a command prompt like this one:

[jkeane@home jkeane]$

Note that different machines will configure your prompt differently. The $ sign indicates that you are logged in as a regular user. The prompt changes to a pound (#) when you are logged in as root.

Issuing Simple Commands:

Often times there are several different ways to do the same thing. For instance, take the simple command 'who', which tells you what users are logged into the computer:

[jkeane@madirish jkeane]$ who
root     :0       Oct 21 16:05
jkeane   pts/0    Oct 21 16:04 (

The who command shows up that root and jkeane are logged into the system. While this information is useful, we can use various 'flags' with the 'who' command to narrow or broaden the information provided. To figure out which flags we can use and what for we can issue the following command:

[jkeane@madirish jkeane]$ who --help
Usage: who [OPTION]... [ FILE | ARG1 ARG2 ]

  -H, --heading     print line of column headings
  -i, -u, --idle    add user idle time as HOURS:MINUTES, . or old
  -l, --lookup      attempt to canonicalize hostnames via DNS
  -m                only hostname and user associated with stdin
  -q, --count       all login names and number of users logged on
  -s                (ignored)
  -T, -w, --mesg    add user's message status as +, - or ?
      --message     same as -T
      --writable    same as -T
      --help        display this help and exit
      --version     output version information and exit

If FILE is not specified, use /var/run/utmp.  /var/log/wtmp as FILE is common.
If ARG1 ARG2 given, -m presumed: `am i' or `mom likes' are usual.

Report bugs to <>.

As you can see there are all sorts of flags that we can use. For starters lets try the '-H' flag, issueing the following command:

[jkeane@madirish jkeane]$ who -H
root     :0       Oct 21 16:05
root     pts/1    Oct 21 16:06
jkeane   pts/0    Oct 21 16:04 (

As you can see this gives us a lot more useful information. Using the --help flag on a command will always yield useful information. The '--help' flag is useful, but sometimes it is very cryptic. To get a more complete description of the command we can use the 'man' command. 'man' is the 'manual' command and provides the manual (or how-to information) for a command. Issuing 'man who' gives us the following:

WHO(1)                         FSF                         WHO(1)

       who - show who is logged on

       who [OPTION]... [ FILE | ARG1 ARG2 ]

       -H, --heading
              print line of column headings

       -i, -u, --idle
              add user idle time as HOURS:MINUTES, . or old

       -l, --lookup
              attempt to canonicalize hostnames via DNS

       -m     only hostname and user associated with stdin

       -q, --count
              all login names and number of users logged on

lines 1-25 
And you have to press the up or down arrows to navigate the manual. Press 'Ctrl+z' or the Control and z key to quit out of the manual viewer so you can get back to your shell prompt. Here's is the full man (or man page) on the 'who' command.

WHO(1)                         FSF                         WHO(1)

       who - show who is logged on

       who [OPTION]... [ FILE | ARG1 ARG2 ]

       -H, --heading
              print line of column headings

       -i, -u, --idle
              add user idle time as HOURS:MINUTES, . or old

       -l, --lookup
              attempt to canonicalize hostnames via DNS

       -m     only hostname and user associated with stdin

       -q, --count
              all login names and number of users logged on

       -s     (ignored)

              -T, -w, --mesg
              add user's message status as +, - or ?

              same as -T

              same as -T

       --help display this help and exit

              output version information and exit

       If    FILE    is   not   specified,   use   /var/run/utmp.
       /var/log/wtmp as FILE is common.  If ARG1 ARG2  given,  -m
       presumed: `am i' or `mom likes' are usual.

       Written by Joseph Arceneaux and David MacKenzie.

       Report bugs to <>.

       Copyright © 2000 Free Software Foundation, Inc.
       This  is  free software; see the source for copying condi­
       tions.  There is NO warranty; not even for MERCHANTABILITY

       The  full documentation for who is maintained as a Texinfo
       manual.   If  the  info  and  who  programs  are  properly
       installed at your site, the command

              info who

       should give you access to the complete manual.

GNU sh-utils 2.0.11        October 2000                    WHO(1)

You can see that there is a lot of power in this simple command, however using the '--help' and 'man' options outlined above you should be able to navigate this command.

Directory Navigation

To move around our shell environment we'll need a few simple commands to start. To find out where you are in the directory tree use the 'pwd' or print working directory command like so:

[jkeane@madirish jkeane]$ pwd

As you can see we're currently in the jkeane directory under the home directory (which is under the root directory). Directory listings always begin with '/' which indicates the root directory or the top of th directory tree. Subsequent directorys are demarcated with a slash ('/'). Now that we know where we are we need to find out what is contained in our directory. We can use the 'ls' or list command to find out what is in our current working directory like so:

[jkeane@madirish jkeane]$ ls
404error.php          images/       mail/          test.txt
ATOD_proposal.doc     img/          Mail_BU/       ticino2.ZIP
bl98.jpg.sda.exe      img2/         mysql/         tmp/
csmpl244.jpg.sda.exe  jkeane        neuchatel.ZIP  tmp-018fba265482a140/
Desktop/              liloconf.txt  personal.php   tmp-020f8d143d1a45a7/
HELLO.C               lilo.txt      tech.php	   who.txt
html@                 links.php     

AS you can see there is a lot in my directory and its difficult to tell what is what. Using the --help, we can find out a little more about how to use the 'ls' command:

[jkeane@madirish jkeane]$ ls --help
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuSUX nor --sort.

  -a, --all                  do not hide entries starting with .
  -A, --almost-all           do not list implied . and ..
  -b, --escape               print octal escapes for nongraphic characters
      --block-size=SIZE      use SIZE-byte blocks
  -B, --ignore-backups       do not list implied entries ending with ~
  -c                         with -lt: sort by, and show, ctime (time of last
                               modification of file status information)
                               with -l: show ctime and sort by name
                               otherwise: sort by ctime
  -C                         list entries by columns
      --color[=WHEN]         control whether color is used to distinguish file
                               types.  WHEN may be `never', `always', or `auto'
  -d, --directory            list directory entries instead of contents
  -D, --dired                generate output designed for Emacs' dired mode
  -f                         do not sort, enable -aU, disable -lst
  -F, --classify             append indicator (one of */=@|) to entries
      --format=WORD          across -x, commas -m, horizontal -x, long -l,
                               single-column -1, verbose -l, vertical -C
      --full-time            list both full date and full time
  -g                         (ignored)
  -G, --no-group             inhibit display of group information
  -h, --human-readable  print sizes in human readable format (e.g., 1K 234M 2G)
      --si                   likewise, but use powers of 1000 not 1024
  -H                         same as `--si' for now; soon to change
                               to conform to POSIX
      --indicator-style=WORD append indicator with style WORD to entry names:
                               none (default), classify (-F), file-type (-p)
  -i, --inode                print index number of each file
  -I, --ignore=PATTERN       do not list implied entries matching shell PATTERN
  -k, --kilobytes            like --block-size=1024
  -l                         use a long listing format
  -L, --dereference          list entries pointed to by symbolic links
  -m                         fill width with a comma separated list of entries
  -n, --numeric-uid-gid      list numeric UIDs and GIDs instead of names
  -N, --literal              print raw entry names (don't treat e.g. control
                               characters specially)
  -o                         use long listing format without group info
  -p, --file-type            append indicator (one of /=@|) to entries
  -q, --hide-control-chars   print ? instead of non graphic characters
      --show-control-chars   show non graphic characters as-is (default
                             unless program is `ls' and output is a terminal)
  -Q, --quote-name           enclose entry names in double quotes
      --quoting-style=WORD   use quoting style WORD for entry names:
                               literal, locale, shell, shell-always, c, escape
  -r, --reverse              reverse order while sorting
  -R, --recursive            list subdirectories recursively
  -s, --size                 print size of each file, in blocks
  -S                         sort by file size
      --sort=WORD            extension -X, none -U, size -S, time -t,
                               version -v
                             status -c, time -t, atime -u, access -u, use -u
      --time=WORD            show time as WORD instead of modification time:
                               atime, access, use, ctime or status; use
                               specified time as sort key if --sort=time
  -t                         sort by modification time
  -T, --tabsize=COLS         assume tab stops at each COLS instead of 8
  -u                         with -lt: sort by, and show, access time
                               with -l: show access time and sort by name
                               otherwise: sort by access time
  -U                         do not sort; list entries in directory order
  -v                         sort by version
  -w, --width=COLS           assume screen width instead of current value
  -x                         list entries by lines instead of by columns
  -X                         sort alphabetically by entry extension
  -1                         list one file per line
      --help                 display this help and exit
      --version              output version information and exit

By default, color is not used to distinguish types of files.  That is
equivalent to using --color=none.  Using the --color option without the
optional WHEN argument is equivalent to using --color=always.  With
--color=auto, color codes are output only if standard output is connected
to a terminal (tty).

Report bugs to <>.

As you can see there are a lot of options we can use with ls. Lets use the -l for long list entries:

[jkeane@madirish jkeane]$ ls -l
total 218160
-rw-r--r--    1 jkeane   jkeane       2363 Jul 25 09:13 404error.php
-rw-r--r--    1 jkeane   jkeane      67072 Jul 11 22:59 ATOD_proposal.doc
-rw-r--r--    1 jkeane   jkeane     311352 Sep 18 09:34 bl98.jpg.sda.exe
-rw-r--r--    1 jkeane   jkeane     251960 Sep 17 08:19 csmpl244.jpg.sda.exe
drwxrwxr-x    3 jkeane   jkeane       4096 Aug 14 16:04 Desktop/
-rw-r--r--    1 jkeane   jkeane        104 May 11  1989 HELLO.C
lrwxrwxrwx    1 jkeane   jkeane         13 May 20 04:03 html -> /var/www/html/
-rw-r-----    1 jkeane   jkeane   170098320 Jun 25 09:48 jkeane
-rw-rw-r--    1 jkeane   jkeane      27947 Oct  1 09:31 liloconf.txt
-rw-rw-r--    1 jkeane   jkeane       8076 Oct  1 09:31 lilo.txt
-rw-r--r--    1 jkeane   jkeane       7438 Oct  1 10:50 links.php
drwx------    2 jkeane   jkeane       4096 Oct  1 17:49 mail/
drwxr-xr-x    2 root     jkeane       4096 Sep 27 08:28 Mail_BU/
drwxr-xr-x    6 root     jkeane       4096 Sep 27 08:27 mysql/
-rw-rw-r--    1 jkeane   jkeane   23670730 Jun 25 17:22 neuchatel.ZIP
-rw-r--r--    1 jkeane   jkeane       5889 Sep 24 12:33 personal.php
-rw-r--r--    1 jkeane   jkeane      11094 Oct  1 10:51 tech.php
-rw-r--r--    1 root     root            0 Jun 25 09:47 test.txt
-rw-rw-r--    1 jkeane   jkeane   24124379 Jun 25 17:10 ticino2.ZIP
drwx------    2 jkeane   jkeane       4096 May 10 07:17 tmp/
drwx------    3 jkeane   jkeane       4096 May 21 06:01 tmp-018fba265482a140/
drwx------    3 jkeane   jkeane       4096 May 21 06:00 tmp-020f8d143d1a45a7/
-rw-rw-r--    1 jkeane   jkeane       2105 Oct 21 16:11 who.txt

Wow! Thats a lot more information than before. Note that you can string flags together, so that 'ls -l -a' is the same thing as 'ls -la'. A lot of these entries above look strange and bear some explaining. The first column is the file or directory permissions (we'll get more into that later), the second column is the number of sub-directories under the directory (files give a '1' value for this column), the third column is the user (see permissions) the fourth is group (a permission also), the fifth is the size, the sixth colun is the datestamp and the last column is the actual name of the file or directory. You can tell the difference between files and directories in two ways. The first way is to look for a '/' after the name, the second is to look for a 'd' in the first column. Many files in this directory have extensions, but file extensions aren't required in Linux like they are in Windows, so these may be misleading. You'll also notice one file named html -> /var/www/html/, this is actualy a symbolic link named 'html' but that points to '/var/www/html'.


cd is the 'change directory' command. It is the most useful command for navigating your directory tree. To change into a directory simply type 'cd ' and then the directory name. For instance, to chance into the 'tmp' directory, issue a 'cd tmp' command. To move up one directory use 'cd ..' and to move up two directories issue 'cd ../..'. You can combine cd directives, so, for instance if you wanted to move up one directory, down into a tmp directory and into a subdirectory 'prog' inside tmp you can issue 'cd ../tmp/prog' and you'll navigate on over. Remember to use 'pwd' to check your location. If you ever get lost simply issue a 'cd' and you'll return to your home directory.

Some more useful BASH commands:


Cat is a useful output program that will show you the contents of a file. For instance, issuing a 'cat who.txt' will print out the contents of the file 'who.txt'. Cat is very useful for searching. By issuing the command

cat who.txt | grep 'GNU'

Will print out the one line in the who.txt program with the word 'GNU'. (more on the grep command and the pipe (|) later).


Use the touch command to update a file's datestamp. For instance, using 'touch myfile.txt' will update the datestamp on the file myfile.txt to the system date. touch can also be used to create a file. Issuing a 'touch myfile.txt' command if myfile.txt does not exist in the current directory will create a new blank file named myfile.txt with the current timestamp.


rm is the command used to delete files and folders. Be careful with the rm command! If you wanted to delete the file 'who.txt' you could issue an 'rm who.txt' and delete it. It is safer to use the '-i' flag with rm (for interactive) as it will prompt you as you are deleting. You can use wildcards in an 'rm'. For instance if you issue 'rm *.txt' you can delete all the files with a '.txt' extension. Note that the '*' is a wildcard, meaning the computer will search for all files and folders with the name * (or anything) and '.txt'. Be extremely careful with wildcards and deleting so you don't rm anything important.


mkdir is the command for creating a directory. If you want to create a new directory named myfiles you can simply issue the command 'mkdir myfiles' and a new directory with the name myfiles will appear in the current working directory. rmdir

mv old new

mv is the command for moving a file. For instance, if I wanted to move the file 'who.txt' into a subdirectory named 'myfiles' I would issue a 'mv who.txt /myfiles' and the file would be moved.

cp filelocation newfilelocation

cp is the command for copy. This can be used to copy files from one location to another while leaving the original. For instance if I wanted to copy the 'who.txt' file into the subdirectory myfiles I would issue a 'cp who.txt myfiles/' and the file would copy into the subdirectory.


find is a useful locating command. For instance if I wanted to find all the files with a '.txt' file extention I could issue a 'find *.txt' and get a listing of all the text files in my directory.

whereis (binary, source, or man file)

whereis is a useful searching tool for locating binaries, sources and man pages. This is very useful if you are searching for the location of a specific program on your computer. For instance, if you wish to find the 'cat' command, you can issue a 'whereis cat' and get a listing of the binary, its source files (if any) and the location of the man pages.

ln -s old new

ln is the 'link' command. Very useful for creating shortcuts. For instance if you have a directory in your home directory that you have to access a lot and don't want to type the full path (for instance /myfiles/myimages/outdoor/), you can make a link. Type 'ln -s myfiles/myimages/outdoor/ outdoor' and you create a new 'virtual' directory that links to the outdoor directory!

(1) (2)