• A shell is a command line interpreter which can constitute the user interface for terminal windows. It can also be used as a mechanism to run scripts, even in non-interactive sessions without a terminal window, as if the commands were being typed in.


  • For example, typing:


  •  
    $ find . -name "*.c" -ls
    
    
  • at the command line accomplishes the same thing as running the following script:


  •  
    #!/bin/bash
    find . -name "*.c" -ls
    
    
  • The #!/bin/bash at the beginning of the script should be familiar to anyone who has developed any kind of script in UNIX environments. Following the magic #! characters goes the name of whatever scripting language interpreter is tasked with executing the following lines. Choices include /usr/bin/perl, /bin/bash, /bin/csh, /usr/bin/python and /bin/sh.


  • Linux provides a wide choice of shells; exactly what is available to use is listed in /etc/shells; e.g. on one system we get:


  •  
    $ cat /etc/shells
    /bin/sh
    /bin/bash
    /sbin/nologin
    /bin/tcsh
    /bin/csh
    /bin/ksh
    /bin/zsh
    
    
  • Most Linux users use the default bash shell, but those with long UNIX backgrounds with other shells may want to override the default. It is worth reviewing the main choices in the historical order of introduction.


  • Any command shell can be invoked merely by typing its name at the command line. A user’s default shell can be changed with the chsh utility.


  • We will concentrate on bash, which is generally the default shell under Linux.


  • Kinds of shells


    1. A login shell is one requiring a password (logging in)


    2. An interactive shell is one in which the standard input/output streams are connected to terminals


    3. A non-interactive shell is one in which the standard input/output streams may be connected to a process, etc.


  • Initialization


  • Interactive shells


  • Login shells:


    1. if /etc/profile exists, source it


    2. if ~/.bash_profile exists, source it


    3. else if ~/.bash_login exists, source it


    4. else if ~/.profile exists, source it


    5. on exit, if ~/.bash_logout exists, source it


  • Non-login shells:


    1. if ~/.bashrc exists, source it


  • Non-interactive shells


  • Despite what the man page says, it seems to be the same as interactive shells.


  • Note that by default, most distributions include a system-wide file (usually /etc/bashrc) from the user’s ~/.bashrc.


  • Aliases permits custom definitions. Typing alias with no arguments gives the list of defined aliases. unalias gets rid of an alias.


  • Some alias examples are shown below:


  •  
    alias l=’ls -laF’
    alias dir=’ls -latF’
    alias rm=’rm -i’
    alias mv=’mv -i’
    alias cp=’cp -ipdv’
    alias df=’df -T’
    alias myyahoo=’firefox https://my.yahoo.com’
    alias diffside=’diff --side-by-side --ignore-all-space’
    
    
  • Environment variables are not limited in length or number. Lots of applications use them, for instance, in order to set default values for configuration options.


  • Examples include HOME, HOST, PATH, and can be set as in PATH: PATH=$HOME/bin:$PATH for example.


  • Note: Putting ./ in your path is a security risk; an unfriendly user might substitute an executable which could be quite harmful. However, if you are on a single user system, you may want to violate this recommendation.


  • Type env (or export) to get a list of presently exported environment variables, set to get the complete set of variables.


  • Some variables to set (use whatever values make sense for you!):


  •  
    EDITOR=/usr/bin/emacs
    CD_PATH=$HOME:/tmp
    LS_COLORS="......"
    PAGER=/usr/bin/less
    HISTSIZE=1000
    
    
  • An environment variable must be exported to propagate its value to a child process. You can do either of the following:


  •  
    $ VAR=value ; export VAR
    $ export VAR=value
    
    
  • You can also make one or more environment variables take effect for just one command:


  •  
    $ LD_LIBRARY_PATH=$PWD DEBUG=3 ./foobar
    
    
  • The default command line prompt is $ for normal users and # for the root or superuser.


  • Customizing the command line prompt is as simple as modifying the value of the environment variable PS1. For example, to set it to display the hostname, user and current directory:


  • Besides the aesthetic value of having a prettier prompt than the default value, embedding more information in the prompt can be quite useful. In the example given we have shown:


  • The machine name - this is useful if you run command line windows on remote machines from your desktop; you can always tell where you are, and this can avoid many errors.


  • The user name - this is particularly important if you are running as a superuser (root) and can help you avoid errors where you take what you think is a benign action and wind up crippling your system.


  • The current directory - it is always important to know where you are. You certainly do not want to do something like rm * in the wrong directory. Here is a table with some of the possible special characters that can be embedded in the PS1 string:


  • Character Meaning Example Output
    \t Time in HH:MM:SS 08:43:40
    \d Date in ”Weekday Month Date” Fri Mar 12
    \n Newline
    \s Shell name bash
    \w Current working directory /usr/local/bin
    \W Basename of current working directory bin
    \u User coop
    \h Hostname c7
    \# Command number (this session) 43
    \! History number (in history file) 1057
  • Note you can embed any other string you like in the prompt.


  • A number of characters have a special meaning and cause certain actions to take place. If you want to print them directly, you usually have to prefix them with a backslash (\) or enclose them in single quotes.


Character Usage
\#> Redirect output descriptor (Default # = 1, stdout)
< Redirect input descriptor
>> Append output
>& Redirect stdout and stderr (equivalent to .. > .. 2>&1)
Character Usage
| Piping
() Execute in a separate shell
&& AND list
|| OR list
; Separate commands
Character Usage
{} Lists
~ Usually means $HOME
$ Parameter substitution
Back tick; used in expression evaluation (also $() syntax)
$(( )) Arithmetic substitution
[] Wildcard expressions, and conditionals
Character Usage
\ End of line, escape sequence
’ ’ Take exactly as is
" " Take as is, but do parameter expansion
Character Usage
& Redirection and putting task in background
# Used for comments
*? Used in wildcard expansion
! Used in history expansion
  • \ (as in \|; try echo | vs echo \|)


  • single quotes: preserves literal value


  • double quotes: same except for $, ‘, and \ .


  • Note you can get a literal quote character by using \’ or \".


  • Try:


 
$ echo $HOME
$ echo \$HOME
$ echo ’$HOME’
$ echo "$HOME"

  • File descriptors:


  • 0 = stdin


  • 1 = stdout


  • 2 = stderr


  • less < file same as less file or less 0< file


  • foo > file ; redirect stdout (same as foo 1> file)


  • foo 2> file ; redirect stderr


  • foo >> file ; append stdout to file


  • foo >& file or foo > file 2>&1;


  • sends stdout and stderr to a file, but foo >>& file does not work ; you have to do foo >> file 2>&1


  • Note that foo > file 2>&1 is not the same as foo 2>&1 > file; the order of arguments is important.


  • A nice non-portable trick you can use in Linux is to take advantage of the device nodes:


  •  
    /dev/stdin
    /dev/stdout
    /dev/stderr
    
    
     
    $ foo > /dev/stderr
    
    


  • Each step in a pipeline is a separate shell; i.e. there is a true pipeline. Be careful with redirection. Also |& does not work.


  • cat nofile | grep string produces an error if nofile does not exist.


  • cat nofile | grep string 2>errs does not work.


  • cat nofile 2>&1 | grep string > errs does not work.


  • cat nofile 2>errors | grep string does work.


  • The tee utility can be very useful for saving output while still looking at the screen:


  •  
    $ foobar | tee filename
    $ foobar 2>&1 | tee filename
    
    
  • There are two mechanisms for substituting the result of an operation into a command:


  •  
    $ ls -l ‘which --skip-alias emacs‘
    $ ls -l $(which --skip-alias emacs)
    
    
  • The second form permits nesting, while the first form does not. Note that the first form has “backticks” (‘) not apostrophes.


  • Arithmetic expressions may be evaluated in two different ways, using the expr utility, or the $((..)) syntax:


  • For x=3:


  • Arithmetic Expression Evaluation Forms


  • Expression Gives
    echo $x + 1 3+1
    echo $(expr $x + 1) 4
    echo $((x+1)) 4
    echo $(($x + 1 )) 4
    echo $(expr $x+1) 3+1
  • The $((..)) syntax is more modern and preferred; expr is less efficient, as it invokes an external program and is trickier to use.


  • Note that $var, $(cmd), ‘cmd‘, and $((...)) all expand inside double quotes.