Arithmetic Operations
Script files must begin with #!/bin/bash. Comment are denoted by #. Code should be properly indented with whitespace.
Arithmetic operations support: +, -, *, /, **, %.
Evaluation methods:
# Method 1
let VAR=arithmetic-expression
# Method 2
VAR=$[arithmetic-expression]
# Method 3
VAR=$((arithmetic-expression))
# Method 4
VAR=$(expr $ARG1 $OP $ARG2)
Note: The multiplication symbol may require escaping.
Augmented assignment:
let i=$i+#
let i+=#
# Operators: +=, -=, *=, /=, %=
Increment:
VAR=$[$VAR+1]
let VAR+=1
let VAR++
Decrement:
VAR=$[$VAR-1]
let VAR-=1
let VAR--
Exercise 1
Create a script that adds three users and calculates the sum of their UIDs.
Exercise 2
Calculate the sum of the UIDs for the 10th and 20th users in /etc/passwd.
uid_10=$(head -10 /etc/passwd | tail -1 | cut -d: -f3)
uid_20=$(head -20 /etc/passwd | tail -1 | cut -d: -f3)
sum=$((uid_10 + uid_20))
Exercise 3
Calculate the total number of blank lines in /etc/rc.d/init.d/functions and /etc/inittab.
blank_lines_1=$(grep '^[[:space:]]*$' /etc/rc.d/init.d/functions | wc -l)
blank_lines_2=$(grep '^[[:space:]]*$' /etc/inittab | wc -l)
total_blank=$((blank_lines_1 + blank_lines_2))
Conditional Testing
Tests determine if a condition is met. Use command exit status: 0 for success, 1-255 for failure.
Test expression syntax:
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
Note: EXPRESSION must be surrounded by whitespace.
Numeric Tests
-eq: equal to-ne: not equal-gt: greater than-ge: greater than or equal-lt: less than-le: less than or equal
Example: [ $num1 -eq $num2 ]
String Tests
==: equal>: greater than (ASCII)<: less than (ASCII)!=: not equal=~: matches pattern on right-z "STRING": true if string is empty-n "STRING": true if string is not empty
Note: Use quotes for strings and prefer [[ ]].
File Tests
Existence:
-a FILEor-e FILE: true if file exists
Existance and type:
-b FILE: block device-c FILE: character device-d FILE: directory-f FILE: regular file-h FILEor-L FILE: symbolic link-p FILE: named pipe-S FILE: socket
File permissions (for current user):
-r FILE: readable-w FILE: writable-x FILE: executable
Special permissions:
-u FILE: has SUID-g FILE: has SGID-k FILE: has sticky bit
Content check:
-s FILE: true if file has size > 0
Timestamp:
-N FILE: modified since last read
Ownership:
-O FILE: current user is owner-G FILE: current user is in group
Binary file comparisons:
FILE1 -ef FILE2: same inode and deviceFILE1 -nt FILE2: FILE1 newer than FILE2FILE1 -ot FILE2: FILE1 older than FILE2
Combining Tests
First method (command-based):
COMMAND1 && COMMAND2
COMMAND1 || COMMAND2
! COMMAND
Second method (expression-based):
-a: logical AND-o: logical OR!: negation
Example: Set hostname to www.magedu.com if current hostname is empty, localhost.localdomain, or localhost.
current_host=$(hostname)
if [[ -z "$current_host" || "$current_host" == "localhost.localdomain" || "$current_host" == "localhost" ]]; then
hostnamectl set-hostname www.magedu.com
fi
Script Exit Status
The default exit status is the result of the last executed command.
Custom exit code:
exit [n]
Note: exit terminates the shell process.
Handling Script Arguments
Positional parameters: $1, $2, ..., ${10}, ${11}, ...
Shift parameters: shift [n]
Exercise: Write a script that accepts two file paths as arguments and calculates their combined blank line count.
#!/bin/bash
blank_count_1=$(grep -c '^$' "$1")
blank_count_2=$(grep -c '^$' "$2")
total=$((blank_count_1 + blank_count_2))
echo "Total blank lines: $total"
Special variables:
$0: script path$#: number of arguments$*: all arguments as a single word$@: all arguments as separate words
Conditional Execution
Single-branch if:
if test_condition; then
commands
fi
Double-branch if:
if test_condition; then
commands_if_true
else
commands_if_false
fi
Example: Add a user if the username passed as an arguement does not exist.
#!/bin/bash
if [ $# -lt 1 ]; then
echo "Please provide a username." >&2
exit 1
fi
if id "$1" &>/dev/null; then
echo "User '$1' already exists."
else
useradd "$1"
echo "User '$1' created."
fi
Example: Output the larger of two numbers provided as arguments.
#!/bin/bash
if [ $# -ne 2 ]; then
echo "Two integers required." >&2
exit 1
fi
if [ $1 -gt $2 ]; then
max=$1
else
max=$2
fi
echo "Larger number: $max"
System Configuration Task
Create a 20GB filesystem with 2048-byte blocks, ext4 format, label 'TEST', and configure it to auto-mount at /testing with ACL support.
Steps:
- Create a 20GB partition using
fdisk. - Format the partition:
mkfs.ext4 -b 2048 -L 'TEST' /dev/DEVICE_NAME
- Add to
/etc/fstab:
LABEL='TEST' /testing ext4 defaults,acl 0 0