Skip to content

Instantly share code, notes, and snippets.

@theking2
Last active May 23, 2026 14:38
Show Gist options
  • Select an option

  • Save theking2/3f3070a7594deae11c23990382f9e344 to your computer and use it in GitHub Desktop.

Select an option

Save theking2/3f3070a7594deae11c23990382f9e344 to your computer and use it in GitHub Desktop.
qcow2 Compression
#!/usr/bin/bash
# Function to get file size in human-readable format
get_size() {
du -h "$1" | cut -f1
}
# Function to get file size in bytes for calculation
get_size_bytes() {
stat -c %s "$1" 2>/dev/null || stat -f %z "$1" 2>/dev/null
}
# Check if filename provided
if [ $# -eq 0 ]; then
echo "Usage: $0 <filename>"
echo "Example: $0 mydisk"
exit 1
fi
# Validate input (no path traversal, no special chars)
filename="$1"
if [[ "$filename" =~ [^a-zA-Z0-9_.-] ]]; then
echo "Error: Filename contains invalid characters"
exit 1
fi
# Check if source exists
source_file="${filename}.qcow2"
if [ ! -f "$source_file" ]; then
echo "Error: Source file '$source_file' not found"
exit 1
fi
# Display initial info
echo "=========================================="
echo "Processing: $source_file"
echo "=========================================="
# Get original size
original_size=$(get_size "$source_file")
original_bytes=$(get_size_bytes "$source_file")
echo "Original size: $original_size"
# Create backup with timing
backup_file="${filename}_backup.qcow2"
echo ""
echo "[1/2] Creating backup..."
backup_start=$(date +%s.%N)
cp "$source_file" "$backup_file"
backup_status=$?
backup_end=$(date +%s.%N)
if [ $backup_status -ne 0 ]; then
echo "Error: Failed to create backup"
exit 1
fi
backup_time=$(echo "$backup_end - $backup_start" | bc)
echo " ✓ Backup created: $backup_file"
echo " ⏱ Time: ${backup_time} seconds"
# Check if qemu-img is available
if ! command -v qemu-img &> /dev/null; then
echo "Error: qemu-img not found"
exit 1
fi
# Compress with timing
echo ""
echo "[2/2] Compressing with qemu-img (using -c flag)..."
compress_start=$(date +%s.%N)
qemu-img convert -O qcow2 -c "$backup_file" "$source_file"
compress_status=$?
compress_end=$(date +%s.%N)
if [ $compress_status -ne 0 ]; then
echo "Error: Compression failed"
exit 1
fi
compress_time=$(echo "$compress_end - $compress_start" | bc)
# Get compressed size
compressed_bytes=$(get_size_bytes "$source_file")
compressed_size=$(get_size "$source_file")
# Calculate size reduction
if [ $original_bytes -gt 0 ]; then
reduction_bytes=$((original_bytes - compressed_bytes))
reduction_percent=$(echo "scale=2; ($reduction_bytes * 100) / $original_bytes" | bc)
# Convert reduction bytes to human readable
if [ $reduction_bytes -gt 1073741824 ]; then
reduction_hr=$(echo "scale=2; $reduction_bytes / 1073741824" | bc)"G"
elif [ $reduction_bytes -gt 1048576 ]; then
reduction_hr=$(echo "scale=2; $reduction_bytes / 1048576" | bc)"M"
elif [ $reduction_bytes -gt 1024 ]; then
reduction_hr=$(echo "scale=2; $reduction_bytes / 1024" | bc)"K"
else
reduction_hr="${reduction_bytes}B"
fi
fi
# Display results
echo ""
echo "=========================================="
echo "COMPLETE! Summary:"
echo "=========================================="
echo "Original size: $original_size"
echo "Compressed size: $compressed_size"
echo "Space saved: $reduction_hr ($reduction_percent%)"
echo ""
echo "Timing:"
echo " Backup: ${backup_time} seconds"
echo " Compression: ${compress_time} seconds"
echo " Total time: $(echo "$backup_time + $compress_time" | bc) seconds"
echo ""
echo "Files:"
echo " Original (compressed): $source_file"
echo " Backup (uncompressed): $backup_file"
echo "=========================================="
# Optional: Show compression ratio
if [ $original_bytes -gt 0 ]; then
ratio=$(echo "scale=2; $compressed_bytes / $original_bytes" | bc)
echo "Compression ratio: ${ratio}:1"
echo "=========================================="
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment