if Statements

Syntax

  1. if commands; then
  2. commands
  3. [elif commands; then
  4. commands...]
  5. [else
  6. commands]
  7. fi
  • Command with exit status of 0 is evaluated as true, otherwise is is evaluated as false.
  • If a list of commands follows if, the last command in the list is evaluated.

    Examples

    true and false are builtin commands that do nothing except terminate with either a 0 and 1 exit status respectively. ```bash function test_if() { if true; then echo ‘true’ else echo ‘false’ fi

    if false; then echo ‘true’ else echo ‘false’ fi }

test_if # call function test_if

true

false

  1. <a name="DayVW"></a>
  2. ### Using `test` or `[ ]`
  3. Both `test` and `[` are actually commands. In bash they are builtins, but they also exist as programs in /usr/bin for use with other shells. <br />`[` command requiring that the `]` character be provided as its **final argument**
  4. ```bash
  5. if test expression; then
  6. commands
  7. fi
  8. # or
  9. if [ expression ]; then
  10. commands
  11. fi

File Expressions

Expression Is true if:
file1 -ef file2 file1 and file2 have the same inode numbers (the two filenames refer to the same file by hard linking).
file1 -nt file2 file1 is newer than file2.
file1 -ot file2 file1 is older than file2.
-b file file exists and is a block-special (device) file.
-c file file exists and is a character-special (device) file.
-d file file exists and is a directory.
-e file file exists.
-f file file exists and is a regular file.
-g file file exists and is set-group-ID.
-G file file exists and is owned by the effective group ID.
-k file file exists and has its “sticky bit” set.
-L file file exists and is a symbolic link.
-O file file exists and is owned by the effective user ID.
-p file file exists and is a named pipe.
-r file file exists and is readable (has readable permission for the effective user).
-s file file exists and has a length greater than zero.
-S file file exists and is a network socket.
-t fd fd is a file descriptor directed to/from the terminal. This can be used to determine whether standard input/output/error is being redirected.
-u file file exists and is setuid.
-w file file exists and is writable (has write permission for the effective user).
-x file file exists and is executable (has execute/search permission for the effective user).

String Expressions

Expression Is true if:
string string is not null.
-n string The length of string is greater than zero.
-z string The length of string is zero.
string1 = string2
string1 == string2
string1 and string2 are equal. Single or double equal signs may be used. The use of double equal signs is greatly preferred, but it is not POSIX compliant.
string1 != string2 string1 and string2 are not equal.
string1 > string2 string1 sorts after string2.
string1 < string2 string1 sorts before string2.

Integers Expressions

Expression Is true if:
integer1 -eq integer2 integer1 is equal to integer2.
integer1 -ne integer2 integer1 is not equal to integer2.
integer1 -le integer2 integer1 is less than or equal to integer2.
integer1 -lt integer2 integer1 is less than integer2.
integer1 -ge integer2 integer1 is greater than or equal to integer2.
integer1 -gt integer2 integer1 is greater than integer2.

Using [[ ]]

Modern versions of bash include a compound command that acts as an enhanced replacement for test. It uses the following syntax:
[[ expression ]]
expression

  • All expressions that test and [ ] support
  • string =~ regex
  • file == filename_pattern ```bash if [[ “$INT” =~ ^-?[0-9]+$ ]]; then echo “$INT is an integer” fi

FILE=foo.bar if [[ $FILE == foo. ]]; then echo “$FILE matches pattern ‘foo.‘“ fi

<a name="ygGs1"></a>
### Using `(( ))` for Integers
`(( ))` is used to perform arithmetic truth tests. An arithmetic truth testresults in true if the result of the arithmetic evaluation is non-zero.<br />`**((integer1 operator integer2))**`<br />`**operator **`

- `**==**` `<` `<=` `>` `>=` ...

See also ??
```bash
if (( INT % 2 == 0 )); then
    echo "$INT is even"
fi

Combining Expressions

Logical Operation test and [] [[ ]] and (( ))
AND -a &&
OR -o ||
NOT ! !
[ "$INT" -ge "$MIN_VAL" -a "$INT" -le "$MAX_VAL" ]
[ ! \( "$INT" -ge "$MIN_VAL" -a "$INT" -le "$MAX_VAL" \) ]

[[ "$INT" -ge "$MIN_VAL" && "$INT" -le "$MAX_VAL" ]]
[[ ! ("$INT" -ge "$MIN_VAL" && "$INT" -le "$MAX_VAL") ]]

Control Operators: Another Way to Branch

command1 && command2
command1 || command2

$ mkdir temp && cd temp
$ [[ -d temp ]] || mkdir temp

while Statement

Syntax

while commands...; do
    commands...
  continue
  break
done

$ while commands...; do commands...; done

Examples

Read lines from a file

#!/bin/bash
# while-read: read lines from a file
while read distro version release; do
  printf "Distro: %s\tVersion: %s\tReleased: %s\n" \
  "$distro" \
    "$version" \
    "$release"
done < distros.txt
#!/bin/bash
# while-read2: read lines from a file
sort -k 1,1 -k 2n distros.txt | while read distro version release; do
    printf "Distro: %s\tVersion: %s\tReleased: %s\n" \
    "$distro" \
    "$version" \
    "$release"
done

until Statement

The until compound command is much like while, except instead of exiting a loop when a non-zero exit status is encountered, it does the opposite.

case Statement

Syntax

case word in
 [pattern [| pattern]...) commands ;;[&]]...
esac

Patterns

Pattern Description
a) Matches if word equals a.
[[:alpha:]]) Matches if word is a single alphabetic character.
???) Matches if word is exactly three characters long.
*.txt) Matches if word ends with the characters .txt.
*) Matches any value of word. It is good practice to include this as the last pattern in a case command to catch any values of word that did not match a previous pattern, that is, to catch any possible invalid values.

Examples

#!/bin/bash
# case-menu: a menu driven system information program
clear
echo "
Please Select:
1. Display System Information
2. Display Disk Space
3. Display Home Space Utilization
0. Quit
"
read -p "Enter selection [0-3] > "
case "$REPLY" in
    0)    echo "Program terminated."
            exit
            ;;
    1)    echo "Hostname: $HOSTNAME"
            uptime
      ;;
    2)    df -h
             ;;
    3)    if [[ "$(id -u)" -eq 0 ]]; then
          echo "Home Space Utilization (All Users)"
        du -sh /home/*
            else
        echo "Home Space Utilization ($USER)"
        du -sh "$HOME"
             fi
             ;;
    *)    echo "Invalid entry" >&2
             exit 1
            ;;
esac
#!/bin/bash
read -p "enter word > "
case "$REPLY" in
    [[:alpha:]]) echo "is a single alphabetic character." ;;
    [ABC][0-9])  echo "is A, B, or C followed by a digit." ;;
    ???)                 echo "is three characters long." ;;
    *.txt)              echo "is a word ending in '.txt'" ;;
    *)                      echo "is something else." ;;
esac
#!/bin/bash
# case4-1: test a character
read -n 1 -p "Type a character > "
echo
case "$REPLY" in
    [[:upper:]])  echo "'$REPLY' is upper case." ;;
    [[:lower:]])  echo "'$REPLY' is lower case." ;;
    [[:alpha:]])  echo "'$REPLY' is alphabetic." ;;
    [[:digit:]])  echo "'$REPLY' is a digit." ;;
    [[:graph:]])  echo "'$REPLY' is a visible character." ;;
    [[:punct:]])  echo "'$REPLY' is a punctuation symbol." ;;
    [[:space:]])  echo "'$REPLY' is a whitespace character." ;;
    [[:xdigit:]]) echo "'$REPLY' is a hexadecimal digit." ;;
esac

Performing Multiple Actions

#!/bin/bash
# case4-2: test a character
read -n 1 -p "Type a character > "
echo
case "$REPLY" in
    [[:upper:]])  echo "'$REPLY' is upper case." ;;&
    [[:lower:]])  echo "'$REPLY' is lower case." ;;&
    [[:alpha:]])  echo "'$REPLY' is alphabetic." ;;&
    [[:digit:]])  echo "'$REPLY' is a digit." ;;&
    [[:graph:]])  echo "'$REPLY' is a visible character." ;;&
     [[:punct:]])  echo "'$REPLY' is a punctuation symbol." ;;&
     [[:space:]])  echo "'$REPLY' is a whitespace character." ;;&
     [[:xdigit:]]) echo "'$REPLY' is a hexadecimal digit." ;;&
esac

for Statement

Traditional Shell Form

Syntax

for variable [in words]; do
        commands
done

$ for variable [in words]; do commands; done

If the optional in words portion of the for command is omitted, for defaults to processing the positional parameters.

Examples

 $ for i in A B C D; do echo $i; done
 $ for i in {A..D}; do echo $i; done
for i in distros*.txt; do
        # By adding a test for file existence, we will ignore a failed expansion.
        if [[ -e "$i" ]]; then
                echo "$i"
        fi
done
#!/bin/bash
# longest-word2: find longest string in a file
for i; do
    if [[ -r "$i" ]]; then
        max_word=
        max_len=0
        for j in $(strings "$i"); do
            len="$(echo -n "$j" | wc -c)"
            if ((len > max_len)); then
                max_len="$len"
                max_word="$j"
            fi
        done
        echo "$i: '$max_word' ($max_len characters)"
    fi
done

C Language Form

Syntax

for (( expression1; expression2; expression3 )); do
        commands
done

# In terms of behavior, this form is equivalent to the following construct.
(( expression1 ))
while (( expression2 )); do
        commands
        (( expression3 ))
done

Examples

#!/bin/bash
# simple_counter: demo of C style for command
for (( i=0; i<5; i=i+1 )); do
        echo $i
done

The C language form of for is useful anytime a numeric sequence is needed.