do/commands/convert-to-webp
2025-07-10 12:06:09 -04:00

145 lines
No EOL
5.1 KiB
Bash

# ----------------------------------------------------
# Finds large images and converts them to the
# WebP format.
# ----------------------------------------------------
function convert_to_webp() {
# The target directory is the first positional argument.
# The --all flag is passed as the second argument from main.
local target_dir_arg="$1"
local all_files_flag="$2"
echo "🚀 Starting WebP Conversion Process 🚀"
# --- Pre-flight Checks ---
if ! setup_cwebp; then
echo "Aborting conversion: cwebp setup failed." >&2
return 1
fi
# --- Initialize and Report Identify Method ---
# Prime the _is_webp function to determine the method and export the choice.
_is_webp ""
# Now that IDENTIFY_METHOD is set, report the choice to the user once.
if [[ "$IDENTIFY_METHOD" == "identify" ]]; then
echo "Using 'identify' command for image type checking."
else
echo "Warning: 'identify' command not found. Falling back to PHP check."
fi
# --- Determine target directory ---
local target_dir="wp-content/uploads"
if [ -n "$target_dir_arg" ]; then
target_dir="$target_dir_arg"
echo "Targeting custom directory: $target_dir"
else
echo "Targeting default directory: $target_dir"
fi
if [ ! -d "$target_dir" ]; then
echo "❌ Error: Cannot find '$target_dir' directory." >&2
return 1
fi
# --- Size and File Discovery ---
local before_size
before_size="$(du -sh "$target_dir" | awk '{print $1}')"
echo "Current directory size: $before_size"
local size_limit_mb=1
local message="larger than ${size_limit_mb}MB"
local find_args=("$target_dir" -type f)
if [[ "$all_files_flag" == "true" ]]; then
message="of all sizes"
else
find_args+=(-size "+${size_limit_mb}M")
fi
find_args+=(\( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.webp" \))
local files
files=$(find "${find_args[@]}")
if [[ -z "$files" ]]; then
echo "✅ No images ${message} found to convert."
return 0
fi
local count
count=$(echo "$files" | wc -l | xargs)
echo "Found $count image(s) ${message} to process using up to 5 concurrent threads..."
echo ""
# --- Helper function for processing a single image ---
# This function will be run in the background for each image.
_process_single_image() {
local file="$1"
local current_num="$2"
local total_num="$3"
# The _is_webp function checks if the file is already in WebP format.
if _is_webp "$file"; then
echo "⚪️ Skipping ${current_num}/${total_num} (already WebP): $file"
return
fi
local temp_file="${file}.temp.webp"
local before_file_size
before_file_size=$(ls -lh "$file" | awk '{print $5}')
# The actual conversion command, output is suppressed for a cleaner log.
"$CWEBP_CMD" -q 80 "$file" -o "$temp_file" > /dev/null 2>&1
# Check if the conversion was successful and the new file has content.
if [ -s "$temp_file" ]; then
mv "$temp_file" "$file"
local after_file_size
after_file_size=$(ls -lh "$file" | awk '{print $5}')
echo "✅ Converted ${current_num}/${total_num} ($before_file_size -> $after_file_size): $file"
else
# Cleanup failed temporary file and report the failure.
rm -f "$temp_file"
echo "❌ Failed ${current_num}/${total_num}: $file"
fi
}
# Export the helper function and its dependencies so they are available to the subshells.
export -f _process_single_image
export -f _is_webp
export -f _is_webp_php
export -f setup_wp_cli
# --- Concurrent Processing Loop ---
local max_jobs=5
local job_count=0
local processed_count=0
# Use process substitution to avoid creating a subshell for the while loop.
# This ensures the main script's 'wait' command can see all background jobs.
while IFS= read -r file; do
processed_count=$((processed_count + 1))
# Run the processing function in the background.
_process_single_image "$file" "$processed_count" "$count" &
# On Linux, use 'wait -n' for a sliding window of jobs.
# On macOS, bash doesn't support 'wait -n', so we skip this
# and let the final 'wait' handle all jobs at once.
if [[ "$(uname)" != "Darwin" ]]; then
job_count=$((job_count + 1))
if (( job_count >= max_jobs )); then
wait -n
job_count=$((job_count - 1))
fi
fi
done < <(echo "$files")
# Wait for all remaining background jobs to complete before proceeding.
wait
# --- Final Summary ---
echo ""
local after_size
after_size="$(du -sh "$target_dir" | awk '{print $1}')"
echo "✅ Bulk conversion complete!"
echo "-----------------------------------------------------"
echo " Directory size reduced from $before_size to $after_size."
echo "-----------------------------------------------------"
}