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:
- Numeric comparisons
- String comparisons
- 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