Skip to content

Instantly share code, notes, and snippets.

@OptimusGREEN
Created June 8, 2025 22:40
Show Gist options
  • Save OptimusGREEN/cf974a3cef1a1afe1eee60d7ae0b09b4 to your computer and use it in GitHub Desktop.
Save OptimusGREEN/cf974a3cef1a1afe1eee60d7ae0b09b4 to your computer and use it in GitHub Desktop.
check directory and update iso to latest version
#!/bin/bash
# Linux ISO Updater Script
# Updates ISO files to latest minor/patch versions while preserving major versions
set -e
# Configuration
ISO_DIR="$(pwd)"
DOWNLOAD_DIR=""
BACKUP_DIR=""
DRY_RUN=false
VERBOSE=false
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
local color=$1
local message=$2
echo -e "${color}${message}${NC}"
}
# Function to show usage
show_usage() {
cat << EOF
Usage: $0 [OPTIONS] [DIRECTORY]
OPTIONS:
-d, --dry-run Show what would be updated without downloading
-v, --verbose Verbose output
-h, --help Show this help message
DIRECTORY:
Path to directory containing ISO files (default: current directory)
Examples:
$0 # Check current directory
$0 /path/to/isos # Check specific directory
$0 --dry-run /path/to/isos # Show what would be updated
EOF
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-d|--dry-run)
DRY_RUN=true
shift
;;
-v|--verbose)
VERBOSE=true
shift
;;
-h|--help)
show_usage
exit 0
;;
-*)
echo "Unknown option $1"
show_usage
exit 1
;;
*)
ISO_DIR="$1"
shift
;;
esac
done
# Set up directory paths after parsing arguments
DOWNLOAD_DIR="${ISO_DIR}/downloads"
BACKUP_DIR="${ISO_DIR}/backup"
# Check if directory exists
if [[ ! -d "$ISO_DIR" ]]; then
print_status $RED "Error: Directory '$ISO_DIR' does not exist"
exit 1
fi
# Create necessary directories
mkdir -p "$DOWNLOAD_DIR" "$BACKUP_DIR"
# Function to extract distribution info from ISO filename
parse_iso_filename() {
local filename=$1
local distro=""
local version=""
local arch=""
local variant=""
# Remove .iso extension
filename="${filename%.iso}"
# Ubuntu patterns (including variants)
if [[ $filename =~ ubuntu-([0-9]+\.[0-9]+)(\.[0-9]+)?-(.+)-(.+) ]]; then
distro="ubuntu"
version="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
variant="${BASH_REMATCH[3]}"
arch="${BASH_REMATCH[4]}"
# Ubuntu variants (mate, studio, cinnamon, etc.)
elif [[ $filename =~ ubuntu(mate|studio|cinnamon)-([0-9]+\.[0-9]+)(\.[0-9]+)?-(.+)-(.+) ]]; then
distro="ubuntu-${BASH_REMATCH[1]}"
version="${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
variant="${BASH_REMATCH[4]}"
arch="${BASH_REMATCH[5]}"
# Linux Mint
elif [[ $filename =~ linuxmint-([0-9]+(\.[0-9]+)?)-(.+)-(.+) ]]; then
distro="linuxmint"
version="${BASH_REMATCH[1]}"
variant="${BASH_REMATCH[3]}"
arch="${BASH_REMATCH[4]}"
# SystemRescue
elif [[ $filename =~ systemrescue-([0-9]+\.[0-9]+)-(.+) ]]; then
distro="systemrescue"
version="${BASH_REMATCH[1]}"
variant=""
arch="${BASH_REMATCH[2]}"
# GParted Live
elif [[ $filename =~ gparted-live-([0-9]+\.[0-9]+\.[0-9]+)-([0-9]+)-(.+) ]]; then
distro="gparted"
version="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}"
variant="live"
arch="${BASH_REMATCH[3]}"
# Clonezilla Live
elif [[ $filename =~ clonezilla-live-([0-9]+\.[0-9]+\.[0-9]+)-([0-9]+)-(.+) ]]; then
distro="clonezilla"
version="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}"
variant="live"
arch="${BASH_REMATCH[3]}"
# Clonezilla Live (date format)
elif [[ $filename =~ clonezilla-live-([0-9]{8})-(.+)-(.+) ]]; then
distro="clonezilla"
version="${BASH_REMATCH[1]}"
variant="${BASH_REMATCH[2]}"
arch="${BASH_REMATCH[3]}"
# TrueNAS SCALE
elif [[ $filename =~ TrueNAS-SCALE-([0-9]+\.[0-9]+\.[0-9]+)(\.[0-9]+)? ]]; then
distro="truenas-scale"
version="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
variant="scale"
arch="amd64"
# Proxmox VE
elif [[ $filename =~ proxmox-ve_([0-9]+\.[0-9]+)-([0-9]+) ]]; then
distro="proxmox-ve"
version="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}"
variant="ve"
arch="amd64"
# Proxmox Backup Server
elif [[ $filename =~ proxmox-backup-server_([0-9]+\.[0-9]+)-([0-9]+) ]]; then
distro="proxmox-backup"
version="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}"
variant="backup-server"
arch="amd64"
# OPNsense
elif [[ $filename =~ OPNsense-([0-9]+\.[0-9]+)-(.+)-(.+) ]]; then
distro="opnsense"
version="${BASH_REMATCH[1]}"
variant="${BASH_REMATCH[2]}"
arch="${BASH_REMATCH[3]}"
# pfSense
elif [[ $filename =~ pfSense-CE-([0-9]+\.[0-9]+\.[0-9]+)-RELEASE-(.+) ]]; then
distro="pfsense"
version="${BASH_REMATCH[1]}"
variant="CE-RELEASE"
arch="${BASH_REMATCH[2]}"
# OpenMediaVault
elif [[ $filename =~ openmediavault_([0-9]+\.[0-9]+\.[0-9]+)-(.+) ]]; then
distro="openmediavault"
version="${BASH_REMATCH[1]}"
variant=""
arch="${BASH_REMATCH[2]}"
# NixOS
elif [[ $filename =~ latest-nixos-(.+)-(.+)-linux ]]; then
distro="nixos"
version="latest"
variant="${BASH_REMATCH[1]}"
arch="${BASH_REMATCH[2]}"
# YunoHost
elif [[ $filename =~ yunohost-(.+)-([0-9]+\.[0-9]+)-(.+)-(.+) ]]; then
distro="yunohost"
version="${BASH_REMATCH[2]}"
variant="${BASH_REMATCH[1]}-${BASH_REMATCH[4]}"
arch="${BASH_REMATCH[3]}"
# UmbrelOS
elif [[ $filename =~ umbrelos-(.+)-usb-installer-([0-9]+\.[0-9]+) ]]; then
distro="umbrelos"
version="${BASH_REMATCH[2]}"
variant="usb-installer"
arch="${BASH_REMATCH[1]}"
# Generic pattern for other distributions
elif [[ $filename =~ ([a-zA-Z]+)-([0-9]+(\.[0-9]+)*) ]]; then
distro="${BASH_REMATCH[1]}"
version="${BASH_REMATCH[2]}"
variant=""
arch=""
fi
echo "$distro|$version|$variant|$arch"
}
# Function to get major version
get_major_version() {
local version=$1
echo "${version%%.*}"
}
# Function to compare versions (returns 0 if v1 < v2, 1 if v1 >= v2)
version_lt() {
local v1=$1
local v2=$2
# Convert versions to arrays
IFS='.' read -ra V1 <<< "$v1"
IFS='.' read -ra V2 <<< "$v2"
# Compare each part
local max_len=${#V1[@]}
[[ ${#V2[@]} -gt $max_len ]] && max_len=${#V2[@]}
for ((i=0; i<max_len; i++)); do
local n1=${V1[i]:-0}
local n2=${V2[i]:-0}
if [[ $n1 -lt $n2 ]]; then
return 0
elif [[ $n1 -gt $n2 ]]; then
return 1
fi
done
return 1 # versions are equal
}
# Function to check for Ubuntu updates
check_ubuntu_updates() {
local current_version=$1
local variant=$2
local arch=$3
local major_version=$(get_major_version "$current_version")
if [[ $VERBOSE == true ]]; then
print_status $BLUE "Checking Ubuntu $major_version.x updates..."
fi
# Ubuntu releases page (simplified check)
local releases_url="http://releases.ubuntu.com/"
local latest_in_series=""
# For Ubuntu, check the specific series directory
local series_url="${releases_url}${major_version}/"
# This is a simplified version - in reality you'd parse the HTML or use API
# For demonstration, we'll simulate finding a newer version
case "$major_version" in
"22")
if [[ "$current_version" < "22.04.4" ]]; then
latest_in_series="22.04.4"
fi
;;
"20")
if [[ "$current_version" < "20.04.6" ]]; then
latest_in_series="20.04.6"
fi
;;
"18")
if [[ "$current_version" < "18.04.6" ]]; then
latest_in_series="18.04.6"
fi
;;
esac
echo "$latest_in_series"
}
# Function to check for Linux Mint updates
check_linuxmint_updates() {
local current_version=$1
local variant=$2
local arch=$3
local major_version=$(get_major_version "$current_version")
if [[ $VERBOSE == true ]]; then
print_status $BLUE "Checking Linux Mint $major_version.x updates..."
fi
local latest_in_series=""
case "$major_version" in
"22")
if version_lt "$current_version" "22"; then
latest_in_series="22"
fi
;;
"21")
if version_lt "$current_version" "21.3"; then
latest_in_series="21.3"
fi
;;
esac
echo "$latest_in_series"
}
# Function to check for TrueNAS SCALE updates
check_truenas_updates() {
local current_version=$1
local variant=$2
local arch=$3
local major_version=$(get_major_version "$current_version")
if [[ $VERBOSE == true ]]; then
print_status $BLUE "Checking TrueNAS SCALE $major_version.x updates..."
fi
local latest_in_series=""
case "$major_version" in
"24")
if version_lt "$current_version" "24.10.2"; then
latest_in_series="24.10.2"
fi
;;
"23")
if version_lt "$current_version" "23.10.2"; then
latest_in_series="23.10.2"
fi
;;
esac
echo "$latest_in_series"
}
# Function to check for Proxmox updates
check_proxmox_updates() {
local current_version=$1
local variant=$2
local arch=$3
local distro_type=$4
local major_version=$(get_major_version "$current_version")
if [[ $VERBOSE == true ]]; then
print_status $BLUE "Checking Proxmox $distro_type $major_version.x updates..."
fi
local latest_in_series=""
if [[ "$distro_type" == "ve" ]]; then
case "$major_version" in
"8")
if version_lt "$current_version" "8.4-1"; then
latest_in_series="8.4-1"
fi
;;
esac
elif [[ "$distro_type" == "backup" ]]; then
case "$major_version" in
"3")
if version_lt "$current_version" "3.4-1"; then
latest_in_series="3.4-1"
fi
;;
esac
fi
echo "$latest_in_series"
}
# Function to download ISO
download_iso() {
local distro=$1
local version=$2
local variant=$3
local arch=$4
local url=$5
local filename=$6
print_status $YELLOW "Downloading $filename..."
if [[ $DRY_RUN == true ]]; then
print_status $BLUE "DRY RUN: Would download from $url"
return 0
fi
# Use wget or curl to download
if command -v wget >/dev/null 2>&1; then
wget -O "$DOWNLOAD_DIR/$filename" "$url"
elif command -v curl >/dev/null 2>&1; then
curl -L -o "$DOWNLOAD_DIR/$filename" "$url"
else
print_status $RED "Error: Neither wget nor curl is available"
return 1
fi
return $?
}
# Function to backup old ISO
backup_iso() {
local iso_file=$1
local backup_name="${iso_file%.iso}.$(date +%Y%m%d_%H%M%S).iso"
if [[ $DRY_RUN == true ]]; then
print_status $BLUE "DRY RUN: Would backup $iso_file to $BACKUP_DIR/$backup_name"
return 0
fi
cp "$ISO_DIR/$iso_file" "$BACKUP_DIR/$backup_name"
print_status $GREEN "Backed up $iso_file"
}
# Main processing function
process_iso_files() {
local iso_count=0
local update_count=0
print_status $BLUE "Scanning directory: $ISO_DIR"
for iso_file in "$ISO_DIR"/*.iso; do
[[ ! -f "$iso_file" ]] && continue
local basename=$(basename "$iso_file")
iso_count=$((iso_count + 1))
print_status $YELLOW "Processing: $basename"
# Parse ISO filename
local info=$(parse_iso_filename "$basename")
IFS='|' read -r distro version variant arch <<< "$info"
if [[ -z "$distro" ]]; then
print_status $RED " Unable to parse ISO filename format"
continue
fi
if [[ $VERBOSE == true ]]; then
print_status $BLUE " Detected: $distro $version ($variant, $arch)"
fi
# Check for updates based on distribution
local latest_version=""
case "$distro" in
"ubuntu"|"ubuntu-mate"|"ubuntu-studio"|"ubuntu-cinnamon")
latest_version=$(check_ubuntu_updates "$version" "$variant" "$arch")
;;
"linuxmint")
latest_version=$(check_linuxmint_updates "$version" "$variant" "$arch")
;;
"truenas-scale")
latest_version=$(check_truenas_updates "$version" "$variant" "$arch")
;;
"proxmox-ve")
latest_version=$(check_proxmox_updates "$version" "$variant" "$arch" "ve")
;;
"proxmox-backup")
latest_version=$(check_proxmox_updates "$version" "$variant" "$arch" "backup")
;;
"systemrescue"|"gparted"|"clonezilla"|"opnsense"|"pfsense"|"openmediavault"|"nixos"|"yunohost"|"umbrelos")
print_status $YELLOW " Update checking available but not implemented for $distro"
print_status $YELLOW " Current version: $version"
continue
;;
*)
print_status $YELLOW " Update checking not implemented for $distro"
continue
;;
esac
if [[ -n "$latest_version" ]]; then
print_status $GREEN " Update available: $version -> $latest_version"
if [[ $DRY_RUN == true ]]; then
print_status $BLUE " DRY RUN: Would update to $latest_version"
else
# Construct download URL (simplified)
local download_url=""
local new_filename=""
case "$distro" in
"ubuntu")
new_filename="ubuntu-${latest_version}-${variant}-${arch}.iso"
download_url="http://releases.ubuntu.com/${latest_version}/$new_filename"
;;
esac
if [[ -n "$download_url" ]]; then
backup_iso "$basename"
if download_iso "$distro" "$latest_version" "$variant" "$arch" "$download_url" "$new_filename"; then
# Move downloaded file to main directory
mv "$DOWNLOAD_DIR/$new_filename" "$ISO_DIR/$new_filename"
# Remove old file
rm "$ISO_DIR/$basename"
print_status $GREEN " Successfully updated to $latest_version"
update_count=$((update_count + 1))
else
print_status $RED " Failed to download update"
fi
fi
fi
else
print_status $GREEN " Already up to date"
fi
echo
done
print_status $BLUE "Summary:"
print_status $BLUE " ISOs processed: $iso_count"
print_status $BLUE " Updates available: $update_count"
}
# Main execution
main() {
print_status $GREEN "Linux ISO Updater"
print_status $GREEN "=================="
echo
if [[ $DRY_RUN == true ]]; then
print_status $YELLOW "DRY RUN MODE - No files will be modified"
echo
fi
# Check for required tools
if ! command -v wget >/dev/null 2>&1 && ! command -v curl >/dev/null 2>&1; then
print_status $RED "Error: Either wget or curl is required"
exit 1
fi
process_iso_files
print_status $GREEN "Done!"
}
# Run main function
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment