#!/bin/bash # Script to compress JPG images with progress bar # Usage: ./minimize-jpg.sh [quality] file1.jpg file2.jpg ... # Usage: ./minimize-jpg.sh [quality] *.jpg # Works as Nemo script with selected files # Default quality: 90 # 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 get quality from user via dialog (for Nemo) get_quality_dialog() { local quality=90 # Try zenity if command -v zenity &> /dev/null; then quality=$(zenity --entry \ --title="JPG Compression Quality" \ --text="Enter compression quality (1-100):" \ --entry-text="90" \ 2>/dev/null) # Check if user cancelled or entered invalid value if [ $? -ne 0 ] || [ -z "$quality" ]; then echo "90" return fi else # No dialog available, use default echo "90" return fi # Validate quality if [[ "$quality" =~ ^[0-9]+$ ]] && [ "$quality" -ge 1 ] && [ "$quality" -le 100 ]; then echo "$quality" else echo "90" fi } check_imagemagick() { if ! command -v mogrify &> /dev/null; then echo -e "${RED}Error: ImageMagick is not installed.${NC}" echo -e "${YELLOW}Install ImageMagick with:${NC}" echo " Ubuntu/Debian: sudo apt-get install imagemagick" echo " CentOS/RHEL: sudo yum install ImageMagick" echo " Arch: sudo pacman -S imagemagick" exit 1 fi } # Main function main() { local quality=90 local file_args=() local quality_was_explicit=false # Parse arguments for arg in "$@"; do if [[ "$arg" =~ ^[0-9]+$ ]] && [ "$arg" -ge 1 ] && [ "$arg" -le 100 ]; then quality="$arg" quality_was_explicit=true else # Add all non-numeric arguments as potential file paths file_args+=("$arg") fi done # Check if ImageMagick is installed check_imagemagick # Create output directory local output_dir="min" if [ ! -d "$output_dir" ]; then mkdir -p "$output_dir" echo -e "${GREEN}Created output directory: $output_dir${NC}" fi # Get files to process local jpg_files=() # If we have file arguments, process them if [ ${#file_args[@]} -gt 0 ]; then # Process file arguments (expand patterns and check files) for pattern in "${file_args[@]}"; do # Use shell expansion for patterns like *.jpg for file in $pattern; do if [[ -f "$file" ]] && [[ "$file" =~ \.(jpg|jpeg|JPG|JPEG)$ ]]; then jpg_files+=("$file") fi done done else echo -e "${RED}Error: No files specified.${NC}" echo -e "${YELLOW}Usage from terminal: $0 [quality] file1.jpg file2.jpg ...${NC}" echo -e "${YELLOW}Usage from terminal: $0 [quality] *.jpg${NC}" echo -e "${YELLOW}Or select files in Nemo and run as script${NC}" exit 1 fi if [ ${#jpg_files[@]} -eq 0 ]; then echo -e "${YELLOW}No JPG files found to process.${NC}" exit 0 fi local total_files=${#jpg_files[@]} local total_size_before=0 local total_size_after=0 # Detect if running from Nemo (file manager) or terminal local use_gui=false local quality_from_dialog=false local original_quality=$quality # Only use GUI if: # 1. Quality wasn't explicitly set # 2. We're likely running from Nemo (NEMO_SCRIPT_SELECTED_FILE_PATHS is set) # 3. zenity is available if [ "$quality_was_explicit" = false ] && [ -n "$NEMO_SCRIPT_SELECTED_FILE_PATHS" ] && command -v zenity &> /dev/null; then local dialog_quality dialog_quality=$(get_quality_dialog) if [ -n "$dialog_quality" ]; then quality="$dialog_quality" quality_from_dialog=true use_gui=true fi fi # Show initial info only for terminal if [ "$use_gui" = false ]; then echo -e "${GREEN}JPG compression started${NC}" echo -e "${BLUE}Quality set to: ${quality}%${NC}" echo -e "${BLUE}Files to process: ${total_files}${NC}" echo -e "${BLUE}Output directory: ${output_dir}${NC}" echo "" fi # Calculate total size before compression for file in "${jpg_files[@]}"; do if [ -f "$file" ]; then size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null) total_size_before=$((total_size_before + size)) fi done # Process each file with appropriate progress display local count=0 if [ "$use_gui" = true ]; then # Use zenity progress bar for GUI ( for file in "${jpg_files[@]}"; do if [ -f "$file" ]; then count=$((count + 1)) filename=$(basename "$file") output_file="${output_dir}/${filename}" echo "# Compressing $filename... ($count/$total_files)" # Copy and compress the file cp "$file" "$output_file" mogrify -quality "$quality" "$output_file" echo "$((count * 100 / total_files))" fi done ) | zenity --progress --title="JPG Compression" --text="Initializing..." --percentage=0 --auto-close # Check if user cancelled if [ $? -ne 0 ]; then zenity --error --text="Compression was cancelled." exit 1 fi else # Use terminal progress bar for file in "${jpg_files[@]}"; do if [ -f "$file" ]; then count=$((count + 1)) filename=$(basename "$file") output_file="${output_dir}/${filename}" # Show terminal progress local percentage=$((count * 100 / total_files)) printf "\r${BLUE}[%3d%%] Processing $filename ($count/$total_files)${NC}" "$percentage" # Copy and compress the file cp "$file" "$output_file" mogrify -quality "$quality" "$output_file" fi done echo "" # New line after progress fi # Calculate total size after compression for file in "${jpg_files[@]}"; do filename=$(basename "$file") output_file="${output_dir}/${filename}" if [ -f "$output_file" ]; then size=$(stat -f%z "$output_file" 2>/dev/null || stat -c%s "$output_file" 2>/dev/null) total_size_after=$((total_size_after + size)) fi done # Calculate statistics local saved_bytes=$((total_size_before - total_size_after)) local saved_percentage=0 if [ "$total_size_before" -gt 0 ]; then saved_percentage=$((saved_bytes * 100 / total_size_before)) fi # Convert bytes to readable format with automatic KB/MB selection local size_before_display local size_after_display local saved_display local unit_before="MB" local unit_after="MB" local unit_saved="MB" # Check if sizes are less than 1MB to display in KB if [ "$total_size_before" -lt 1048576 ]; then size_before_display=$((total_size_before / 1024)) unit_before="KB" else size_before_display=$((total_size_before / 1024 / 1024)) fi if [ "$total_size_after" -lt 1048576 ]; then size_after_display=$((total_size_after / 1024)) unit_after="KB" else size_after_display=$((total_size_after / 1024 / 1024)) fi if [ "$saved_bytes" -lt 1048576 ]; then saved_display=$((saved_bytes / 1024)) unit_saved="KB" else saved_display=$((saved_bytes / 1024 / 1024)) fi # Show final report if [ "$use_gui" = true ]; then # Show report with zenity local report_message="✓ Compression completed!\n\n" report_message+="Files processed: ${total_files}\n" report_message+="Original size: ${size_before_display} ${unit_before}\n" report_message+="Compressed size: ${size_after_display} ${unit_after}\n" report_message+="Space saved: ${saved_display} ${unit_saved} (${saved_percentage}%)\n" report_message+="Quality used: ${quality}%\n" report_message+="Output directory: ${output_dir}/" zenity --info --title="JPG Compression Complete" --text="$report_message" else # Show report in terminal echo "" echo -e "${GREEN}✓ Compression completed!${NC}" echo "" echo -e "${BLUE}Statistics:${NC}" echo -e " Files processed: ${total_files}" echo -e " Original size: ${size_before_display} ${unit_before}" echo -e " Compressed size: ${size_after_display} ${unit_after}" echo -e " Space saved: ${saved_display} ${unit_saved} (${saved_percentage}%)" echo -e " Quality used: ${quality}%" echo -e " Output directory: ${output_dir}/" fi } # Show help if requested if [[ "$1" == "-h" || "$1" == "--help" ]]; then echo -e "${GREEN}Script to compress JPG images${NC}" echo "" echo -e "${YELLOW}Usage:${NC}" echo " $0 [quality] file1.jpg file2.jpg ..." echo " $0 [quality] *.jpg" echo " Or select files in Nemo file manager and run as script" echo "" echo -e "${YELLOW}Parameters:${NC}" echo " quality Compression quality (1-100, default: 90)" echo " files JPG/JPEG files to compress" echo "" echo -e "${YELLOW}Examples:${NC}" echo " $0 photo1.jpg photo2.jpg # Compress specific files with quality 90" echo " $0 85 *.jpg # Compress all JPG files with quality 85" echo " $0 75 vacation/*.jpeg # Compress JPEG files in vacation folder" echo "" echo -e "${BLUE}Note: Compressed images will be saved in the 'min' subdirectory${NC}" echo -e "${BLUE} When used as Nemo script, a dialog will ask for quality${NC}" echo -e "${BLUE} Requires zenity for GUI dialog${NC}" exit 0 fi # Execute main main "$@"