Logo  

CS469 - Linux and Unix Administration and Networking

Bash Scripting - Part 1

Unix philosophy:

"Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface." - Doug McIlroy

Invocation: (#!/bin/bash, command line arguments)

Text files that have been made executable (chmod +x file) can be made into scripts provided the first line begins with "#!" followed by the path of the program that will be fed the text file as it's stdin.

  • One (and only one) additional command line agument can be passed to the program specified by the #! escape sequence.

Examples

#!/bin/bash

  • Interprets the rest of the file as a bash script.

#!/bin/tail -n+1

  • Outputs the file but not the first line (the above line)

Various types of shells one can use on Unix:

Bourne sh-compatible: sh, bash, ash, dash, ksh, zsh

C shells: csh, tcsh

  • Others purely for scripting: perl, python, php, node.js, etc.
  • We will focus on bash scripting (A IEEE Standard 1003.1 conformant shell)

Bash invocation:

#!/bin/bash [-l] [-c 'command']
-l = login shell

interactive login shell startup scripts:

These scripts are read and executed by a bash shell on startup if it is a login shell (one that you login with or invoke with the -l option)

/etc/profile
~/.bash_profile
~/.bash_login
~/.profile

interactive, non-login startup scripts:

This script executed by any bash script that is not a login shell

~/.bashrc

login shell exit scripts:

This script is run when a login shell exits.

~/.bash_logout

Grammar:

Comments

Comments are denoted by an unquoted, unescaped `#' and continue to the end of the line.

(command) Pipelines:

[time [-p]] [!] <command1> [ | or |& <command2> ...]

  • Connects the output (stdout) of <command1> to the input (stdin) of <command2>.
time Displays the amount of user/system/wall clock time used.
! Invert the return status of the pipeline (i.e. success becomes failure, failure becomes success.)
| Pipes stdout of <command1> to stdin of <command2>
|& Pipes both stdout and stderr from <command1>
Same as '2>&1 |' - redirect stderr to stdout, then stdout through the pipe

Examples:

> ls -la | less

  • Pipe 'ls -la' to a pager

> ps aux | grep "^sbaker"

  • Print all processes by the user sbaker

> man gcc 2> /dev/null | wc -l | awk '{ print $1/66 }'

  • Find the number of pages in the gcc manpage

> time sleep 1

  • Find out how long it takes to sleep for one second.

(command) Lists:

one or more pipelines seperated by ;, &, &&, or ||

Precidence:
|| or &&
; or &


command1 ; command2

  • Run command2 after running command1

command1 & command2

  • Run both command2 and command1 at the same time, with command1 in the background.

command1 && command2

  • command2 run iff command1 returns 0 exit status same as:
    if command1; then command2; fi

command1 || command2

  • command2 run iff command1 returns non-0 exit status same as:
    if ! command1; then command2; fi

Compound commands:

( list )

  • executed in a sub-shell. variables assigned are not visible in the calling shell.

{ list; }

  • executed in the current shell, useful for redirecting the input/output of all programs inside the {} at once:
    { command; command; command; } < input > file

(( expr ))

  • arithmetic expression (C like), if value is non-zero, return status is 0, else 1. (variables also don't need $'s inside of (()):
    example:
    if (( a >= 0 && a <= 10 )); then echo "a in range 0-10"; fi

[[ expr ]]

  • conditional expression, returns status of 0 or 1. (man test) for more information on all the test conditions: examples:
    [[ -f "$file" ]]; File $file exists and is regular
    [[ -z $str ]]; $str is an empty string
    [[ $str == wc ]]; $str matched wild-card pattern
    [[ $str =~ regex ]] $str matches regex pattern

I/O redirections:

command [&]>[>] file

  • Output stdout (and stderr if '&' is added) to file, appending to file if an extra '>' is added.

Examples:

ls -la > output
ps ax >> output
man gcc &>> output

command < file

  • Connects file to the input (stdin) of command. Example:
    wc -l < output

command <<[-] label
...
label

  • Connect the text after the command up to label to the stdin of the command (called a HEREDOC). Lines are variable expanded unless label is quoted (i.e. "label".)

Quoting:

'...'

  • As-is, no expansion.

$'...'

  • Adds backslash escaped sequences, but otherwise like ''.

"..."

  • Allows variable expansion.

$"..."

  • Translates to the current locale, returns "" string.