Topics

  • Argument processing
  • File and directory operations
  • Conditional statements and loops
  • Test operators

exercise_01.sh

executable safe: yes
#!/bin/bash
# @type: executable
# @requires: none
# @safe: yes
set -euo pipefail

# Exercise 1: Create a script that takes two numbers as command-line arguments and prints their sum.
#
# Task: Accept two numeric arguments, validate them, and calculate their sum.

if [ $# -ne 2 ]; then
    echo "Error: Two numbers required"
    echo "Usage: $0 number1 number2"
    exit 1
fi

if ! [[ "$1" =~ ^-?[0-9]+$ ]] || ! [[ "$2" =~ ^-?[0-9]+$ ]]; then
    echo "Error: Both arguments must be numbers"
    exit 1
fi

sum=$(( $1 + $2 ))
echo "Sum of $1 and $2 is: $sum"

exercise_02.sh

executable safe: yes
#!/bin/bash
# @type: executable
# @requires: none
# @safe: yes
set -euo pipefail

# Exercise 2: Write a script that checks if a file provided as a command-line argument exists.
#
# Task: Accept a filename as an argument and check if it exists as a regular file,
# directory, or doesn't exist at all.

if [ $# -eq 0 ]; then
    echo "Error: No filename provided"
    echo "Usage: $0 filename"
    exit 1
fi

filename="$1"

if [ -f "$filename" ]; then
    echo "File '$filename' exists"
    ls -lh "$filename"
    exit 0
elif [ -d "$filename" ]; then
    echo "'$filename' is a directory, not a regular file"
    exit 2
else
    echo "File '$filename' does not exist"
    exit 1
fi

exercise_03.sh

executable safe: yes
#!/bin/bash
# @type: executable
# @requires: none
# @safe: yes
set -euo pipefail

# Exercise 3: Create a script that creates a directory if it doesn't already exist.
#
# Task: Accept a directory name as an argument and create it if it doesn't exist.
# Handle cases where a file with the same name exists.

if [ $# -eq 0 ]; then
    echo "Error: No directory name provided"
    echo "Usage: $0 directory_name"
    exit 1
fi

dirname="$1"

if [ -d "$dirname" ]; then
    echo "Directory '$dirname' already exists"
    ls -ld "$dirname"
    exit 0
fi

if [ -e "$dirname" ]; then
    echo "Error: '$dirname' exists but is not a directory"
    exit 1
fi

if mkdir -p "$dirname"; then
    echo "Directory '$dirname' created successfully"
    ls -ld "$dirname"
    exit 0
else
    echo "Failed to create directory '$dirname'"
    exit 1
fi

exercise_04.sh

executable safe: yes
#!/bin/bash
# @type: executable
# @requires: none
# @safe: yes
set -euo pipefail

# Exercise 4: Create a script that performs a numeric countdown from a given starting number to 1.
# If no argument is provided or the argument is not a positive integer, print an error message and exit.
#
# Task: Count down from a specified positive integer to 1, with input validation.

if [ $# -eq 0 ]; then
    echo "Error: No starting number provided"
    echo "Usage: $0 positive_integer"
    exit 1
fi

start="$1"

if ! [[ "$start" =~ ^[0-9]+$ ]]; then
    echo "Error: '$start' is not a valid positive integer"
    exit 1
fi

if [ "$start" -le 0 ]; then
    echo "Error: Number must be greater than 0"
    exit 1
fi

echo "Starting countdown from $start..."
for ((i=start; i>=1; i--)); do
    echo "$i"
done

echo "Countdown complete!"

exercise_05.sh

executable safe: yes
#!/bin/bash
# @type: executable
# @requires: none
# @safe: yes
set -euo pipefail

# Exercise 5: Write a script that lists all executable regular files in the current directory.
#
# Task: Find all files in the current directory that are both regular files and executable,
# then display them with file details.

echo "Executable files in current directory:"

count=0

for file in *; do
    if [ -f "$file" ] && [ -x "$file" ]; then
        ls -lh "$file"
        ((count++))
    fi
done

echo "Total executable files found: $count"

if [ $count -eq 0 ]; then
    echo "No executable files found"
    exit 1
else
    exit 0
fi

exercise_extra_01.sh

executable safe: yes
#!/bin/bash
# @type: executable
# @requires: none
# @safe: yes
set -euo pipefail

# Extra Exercise 1: Write a script that takes a filename as an argument
# and displays the number of lines, words, and characters in the file.
# If no argument is provided, print a usage message.

if [ $# -eq 0 ]; then
    echo "Usage: $0 <filename>"
    exit 1
fi

FILE="$1"

if [ ! -f "$FILE" ]; then
    echo "Error: File '$FILE' does not exist or is not a regular file."
    exit 1
fi

LINES=$(wc -l < "$FILE")
WORDS=$(wc -w < "$FILE")
CHARS=$(wc -c < "$FILE")

echo "File: $FILE"
echo "Lines: $LINES"
echo "Words: $WORDS"
echo "Characters: $CHARS"

exercise_extra_02.sh

executable safe: yes
#!/bin/bash
# @type: executable
# @requires: none
# @safe: yes
set -euo pipefail

# Extra Exercise 2: Write a script that generates a simple multiplication table
# for a number provided as an argument. Display the table from 1 to 10.
# Use a for loop with the seq command.

if [ $# -eq 0 ]; then
    echo "Usage: $0 <number>"
    exit 1
fi

NUM="$1"

# Validate that the argument is a number
if ! [[ "$NUM" =~ ^-?[0-9]+$ ]]; then
    echo "Error: '$NUM' is not a valid integer."
    exit 1
fi

echo "Multiplication table for $NUM:"
echo "=============================="

for i in $(seq 1 10); do
    RESULT=$((NUM * i))
    printf "%d x %2d = %d\n" "$NUM" "$i" "$RESULT"
done

exercise_extra_03.sh

executable safe: yes
#!/bin/bash
# @type: executable
# @requires: none
# @safe: yes
set -euo pipefail

# Extra Exercise 3: Write a script that monitors a given log file and
# counts the number of ERROR, WARNING, and INFO lines.
# Accept the log file path as an argument. Use grep -c for counting.

if [ $# -eq 0 ]; then
    echo "Usage: $0 <logfile>"
    exit 1
fi

LOGFILE="$1"

if [ ! -f "$LOGFILE" ]; then
    echo "Error: File '$LOGFILE' does not exist."
    exit 1
fi

ERRORS=$(grep -ci "error" "$LOGFILE")
WARNINGS=$(grep -ci "warning" "$LOGFILE")
INFOS=$(grep -ci "info" "$LOGFILE")
TOTAL=$(wc -l < "$LOGFILE")

echo "Log file analysis: $LOGFILE"
echo "=============================="
echo "Total lines:  $TOTAL"
echo "ERROR lines:  $ERRORS"
echo "WARNING lines: $WARNINGS"
echo "INFO lines:   $INFOS"

if [ "$ERRORS" -gt 0 ]; then
    echo ""
    echo "Last 5 ERROR lines:"
    grep -i "error" "$LOGFILE" | tail -5
fi