Shell Script Arithmetic and Conditional Testing

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 FILE or -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 FILE or -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 device
  • FILE1 -nt FILE2: FILE1 newer than FILE2
  • FILE1 -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:

  1. Create a 20GB partition using fdisk.
  2. Format the partition:
mkfs.ext4 -b 2048 -L 'TEST' /dev/DEVICE_NAME
  1. Add to /etc/fstab:
LABEL='TEST' /testing ext4 defaults,acl 0 0

Tags: bash shell-scripting Linux arithmetic conditional-testing

Posted on Fri, 22 May 2026 16:35:20 +0000 by stanleyg