Linux Bible

command1 | command2

Don’t think of piping as running two commands back to back. The Linux system actually runs both commands at the same time, linking them together internally in the system. As the first command produces output, it’s sent immediately to the second command. No inter- mediate files or buffer areas are used to transfer the data.

– page 282


The bash shell includes the expr command to stay compatible with the Bourne shell; how- ever, it also provides a much easier way of performing mathematical equations. In bash, when assigning a mathematical value to a variable, you can enclose the mathematical equa- tion using a dollar sign and square brackets ($[ operation ]): var1=$[1 + 5]

– page 287

There’s one major limitation to performing math in the bash shell script. The bash shell mathematical operators support only integer arithmetic. This is a huge limi- tation if you’re trying to do any sort of real-world mathematical calculations.

The z shell (zsh) provides full floating-point arithmetic operations. If you require floating-point calculations in your shell scripts, you might consider checking out the z shell.


bc bash calculator

variable=$(echo "options; expression" | bc)
var1=$(echo "scale=4; 3.44 / 5" | bc)

The bc command recognizes input redirection, allowing you to redirect a file to the bc command for processing

variable=$(bc << EOF
options
statements expressions
EOF
)
var5=$(bc << EOF
scale = 4
a1 = ( $var1 * $var2)
b1 = ($var3 * $var4) a1 + b1
EOF
)

Bash structured commands

if-then

if command
then
commands
elif command2
then
elif command3
then
else
commands
fi

When the command in the if statement line returns with a zero exit status code, the com- mands listed in the then section are executed, just as in a normal if-then statement. When the command in the if statement line returns a non-zero exit status code, the bash shell executes the commands in the else section.

if pwd
then
echo "It worked"
fi

By putting a semicolon at the end of the command to evaluate, you can include the then statement on the same line, which looks closer to how if-then statements are handled in some other programming languages.

if command; then
commands
fi

test command

The test command provides a way to test different conditions in an if-then statement. If the condition listed in the test command evaluates to TRUE, the test command exits with a zero exit status code. This makes the if-then statement behave in much the same way that if-then statements work in other programming languages. If the condition is FALSE, the test command exits with a non-zero exit status code, which causes the if- then statement to exit.

if test condition; then
    commands
fi

The bash shell provides an alternative way of testing a condition without declaring the test command in an if-then statement. The square brackets define the test condition.

☝🏼 Be careful; you must have a space after the first bracket and a space before the last bracket, or you’ll get an error message

if [ condition ]; then
    commands
fi

The test command and test conditions can evaluate three classes of conditions:

  1. Numeric comparisons
  2. String comparisons
  3. File comparisons

Numeric comparisons

Comparison Description
n1 -eq n2 Checks if n1 is equal to n2
n1 -ge n2 Checks if n1 is greater than or equal to n2
n1 -gt n2 Checks if n1 is greater than n2
n1 -le n2 Checks if n1 is less than or equal to n2
n1 -lt n2 Checks if n1 is less than n2
n1 -ne n2 Checks if n1 is not equal to n2

The numeric test conditions can be used to evaluate both numbers and variables:

value1=10
value2=11

if [ $value1 -gt 5 ]; then
    echo "The test value $value1 is greater than 5"
fi

if [ $value1 -eq $value2 ]; then
    echo "The values are equal"
else
    echo "The values are different"
fi

💥 There is a limitation to the test numeric conditions concerning floating-point values, you will get an error integer expression expected. The bottom line is that you cannot use floating-point values for test conditions:

value1=5.555
if [ $value1 -gt 5 ]; then
    echo "The test value $value1 is greater than 5"
fi

String comparisons

Comparison Description
str1 = str2 Checks if str1 is the same as string str2
str1 != str2 Checks if str1 is not the same as str2
str1 < str2 Checks if str1 is less than str2
str1 > str2 Checks if str1 is greater than str2
-n str1 Checks if str1 has a length greater than zero
-z str1 Checks if str1 has a length of zero
  • The greater-than and less-than symbols must be escaped, or the shell uses them as redirection symbols, with the string values as filenames. if [ $val1 \> $val2 ]; then ...
  • The greater-than and less-than order is not the same as that used with the sort command. The sort command handles uppercase lettters opposite to the way the test conditions consider them. Capitalized letters are treated as less than lowercase letters in test comparisons. However, the sort command does the opposite. When you put the same strings in a file and use the sort command, the lowercase letters appear first. This is due to different ordering techniques.

💥 Test comparisons use standard ASCII ordering, using each character’s ASCII numeric value to determine the sort order. The sort command uses the sorting order defined for the system locale language settings. For the English language, the locale settings specify that lowercase letters appear before uppercase letters in sorted order.

☝🏼 The test command and test expressions use the standard mathematical comparison symbols for string compari- sons and text codes for numerical comparisons. This is a subtle feature that many programmers manage to get reversed. If you use the mathematical comparison symbols for numeric values, the shell interprets them as string values and may not produce the correct results.

☝🏼 Empty and uninitialized variables can have catastrophic effects on your shell script tests. If you’re not sure of the contents of a variable, it’s always best to test if the variable contains a value using -n or -z before using it in a numeric or string comparison.

File comparisons

Comparison Description
-d file Checks if file exists and is a directory
-e file Checks if file exists, it can be a directory
-f file Checks if file exists and is a file
-r file Checks if file exists and is readable
-s file Checks if file exists and is not empty
-w file Checks if file exists and is writable
-x file Checks if file exists and is executable
-O file Checks if file exists and is owned by the current user
-G file Checks if file exists and the default group is the same as the current user
file1 -nt file2 Checks if file1 is newer than file2
file1 -ot file2 Checks if file1 is older than file2

Compound Testing

  • [ condition1 ] && [ condition2 ]
  • [ condition1 ] || [ condition2 ]

Advanced if-then Features

  • Double parentheses for mathematical expressions
  • Double square brackets for advanced string handling functions

Double parentheses

The double parentheses command allows you to incorporate advanced mathematical formulas in your comparisons. The test command allows for only simple arithmetic operations in the comparison. The double parentheses command provides more mathematical symbols, which programmers who have used other programming languages may be familiar with using. Here’s the format of the double parentheses command:

(( expression ))
Symbold Description
val++ Post-increment
val– Post-decrement
++val Pre-increment
–val Pre-decrement
! Logical negation
~ Bitwise negation
** Exponentiation
« Left bitwise shift
» Right bitwise shift
& Bitwise Boolean AND
| Bitwise Boolean OR
&& Logical AND
|| Logical OR
if (( $val1 ** 2 > 90 )); then
    (( val2 = $val1 ** 2 ))
    echo "The square of $val1 is $val2"
fi

Double brackets

The double bracket command provides advanced features for string comparisons. Here’s the double bracket command format:

[[ expression ]]

The double bracketed expression uses the standard string comparison used in the test evaluations. However, it provides an additional feature that the test evaluations don’t — pattern matching.

☝🏼 Double brackets work fine in the bash shell. Be aware, however, that not all shells support double brackets.

if [[ $USER == r* ]]; then
    echo "Hello $USER"
else
    echo "Sorry, I do not know you"
fi

Notice in the preceding script that double equal signs (==) are used. These double equal signs designate the string to the right (r*) as a pattern, and pattern matching rules are applied. The double bracket command matches the $USER environment variable to see whether it starts with the letter r.

case Command

case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac

for Command

for var in list
do
    commands
done