Day 9 Task: Shell Scripting Challenge Directory Backup with Rotation

Faizan ShaikhFaizan Shaikh
4 min read

The script will create timestamped backups and retain only the last 3 backups by deleting the older ones. Let’s call it backup_with_rotation.sh:

vim backup_with_rotation.sh :

#!/bin/bash

<< readme
This is script for backup with 3 day rotation

Useage:
./backup.sh <path to your source means what u want to backup > <path to backup folder where u want to store u r backup>
readme

function display_usage {
        echo "Usage:./backup.sh <path to your source > <path to backup folder>"
        echo "./backup.sh <what to backup> <where to backup>"
}

if [ $# -eq 0 ]; then
        display_usage
fi

source_dir=$1
timestamp=$(date '+%Y-%m-%d-%H-%M-%S')
backup_dir=$2

function create_backup {

        zip -r "${backup_dir}/backup_${timestamp}.zip" "${source_dir}" > /dev/null

        if [ $? -eq 0 ]; then
                echo "backup generated successfully for ${timestamp}"
        fi

}

function perform_rotation {

        backups=($(ls -t "${backup_dir}/backup_"*.zip 2>/dev/null))

        if [ "${#backups[@]}" -gt 3 ]; then
                echo "Performing rotation for 3 days"

                backups_to_remove=("${backups[@]:3}")

                for backup in "${backups_to_remove[@]}";
                do
                        rm -f ${backup}
                done
        fi

}


create_backup
perform_rotation

Here’s a detailed explanation of your bash script line by line:

Header and Script Description

#!/bin/bash
  • This specifies the script should be run using the bash shell.
<< readme
This is script for backup with 3 day rotation

Usage:
./backup.sh <path to your source means what u want to backup > <path to backup folder where u want to store u r backup>
readme
  • << readme is a multi-line comment block that provides a brief description of the script. It explains the purpose of the script (backup with 3-day rotation) and how to use it (pass the source folder and the backup folder paths).

Function: Display Usage Information

function display_usage {
        echo "Usage:./backup.sh <path to your source > <path to backup folder>"
        echo "./backup.sh <what to backup> <where to backup>"
}
  • This function display_usage simply prints out how the user should run the script if they don't provide the required arguments.

Argument Check

if [ $# -eq 0 ]; then
        display_usage
fi
  • if [ $# -eq 0 ]; then: This checks if the number of arguments ($#) passed to the script is 0.

  • If no arguments are passed, the script calls the display_usage function to inform the user how to use it.

Defining Variables for Source and Backup Paths

source_dir=$1
timestamp=$(date '+%Y-%m-%d-%H-%M-%S')
backup_dir=$2
  • source_dir=$1: Assigns the first argument passed to the script (source directory) to the variable source_dir.

  • timestamp=$(date '+%Y-%m-%d-%H-%M-%S'): Generates a timestamp in the format YYYY-MM-DD-HH-MM-SS to be used in the backup filename.

  • backup_dir=$2: Assigns the second argument (backup directory) to the variable backup_dir.

Function: Create Backup

function create_backup {
        zip -r "${backup_dir}/backup_${timestamp}.zip" "${source_dir}" > /dev/null

        if [ $? -eq 0 ]; then
                echo "backup generated successfully for ${timestamp}"
        fi
}
  • This function creates a zip backup of the source directory.

    • zip -r "${backup_dir}/backup_${timestamp}.zip" "${source_dir}" > /dev/null: This compresses the source directory (source_dir) into a zip file named backup_<timestamp>.zip inside the backup directory (backup_dir). The > /dev/null redirects any output from the zip command to null (meaning it hides the details of the zip creation).
  • if [ $? -eq 0 ]; then: This checks if the previous command (zip) was successful. $? stores the exit status of the last command (0 means success).

    • If the backup is created successfully, it prints: "backup generated successfully for ${timestamp}".

Function: Perform Rotation (3-day Backup Rotation)

function perform_rotation {
        backups=($(ls -t "${backup_dir}/backup_"*.zip 2>/dev/null))

        if [ "${#backups[@]}" -gt 3 ]; then 
                echo "Performing rotation for 3 days" 

                backups_to_remove=("${backups[@]:3}") 

                for backup in "${backups_to_remove[@]}"; 
                do
                        rm -f ${backup}
                done
        fi
}
  • This function manages backup file rotation, ensuring only the last 3 backups are kept.

    • backups=($(ls -t "${backup_dir}/backup_"*.zip 2>/dev/null)): This lists all zip files in the backup directory that match the pattern backup_*.zip, sorted by modification time (-t flag). The most recent files appear first. The 2>/dev/null suppresses any errors if no backup files exist.
  • if [ "${#backups[@]}" -gt 3 ]; then: Checks if the number of backup files (${#backups[@]}) is greater than 3.

    • If there are more than 3 backups, it prints "Performing rotation for 3 days".
  • backups_to_remove=("${backups[@]:3}"): Creates an array of backups to delete, starting from the 4th file onward ("${backups[@]:3}" skips the first 3 recent backups).

  • for backup in "${backups_to_remove[@]}"; do: Loops through each backup file in the backups_to_remove array.

    • rm -f ${backup}: Removes the old backup files.

Running the Functions

create_backup
perform_rotation
  • create_backup: Calls the function to create a new backup.

  • perform_rotation: Calls the function to delete old backups if more than 3 exist.


Summary

  • This script backs up a specified source directory, creating a timestamped zip file in the backup directory.

  • It keeps only the 3 most recent backups and automatically deletes older ones.

0
Subscribe to my newsletter

Read articles from Faizan Shaikh directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Faizan Shaikh
Faizan Shaikh