Disk Image Management on macOS
Create and manage disk images on your MacFleet devices for efficient data packaging, software distribution, and system deployment. This tutorial covers disk image creation from folders, advanced formatting options, encryption, compression, and enterprise-scale image management workflows.
Understanding Disk Images
Disk images are file containers that replicate the exact structure and content of storage volumes, providing powerful capabilities for enterprise deployment:
Benefits of Disk Images
- Software Distribution - Package applications and configurations for deployment
- Data Backup - Create portable snapshots of folder contents
- System Deployment - Standardize configurations across multiple devices
- Secure Transport - Encrypted images for sensitive data transfer
- Version Control - Maintain different versions of software packages
- Network Efficiency - Compressed images reduce transfer time
Disk Image Types
.dmg
- Apple Disk Image (primary format).iso
- ISO 9660 format for cross-platform compatibility.sparseimage
- Sparse images that grow as needed.sparsebundle
- Bundle format for network storage
Basic Disk Image Creation
Simple Folder to Disk Image
#!/bin/bash
# Create basic disk image from folder
SOURCE_FOLDER="$1"
IMAGE_NAME="$2"
OUTPUT_PATH="$3"
if [[ -z "$SOURCE_FOLDER" || -z "$IMAGE_NAME" || -z "$OUTPUT_PATH" ]]; then
echo "❌ Usage: $0 <source_folder> <image_name> <output_path>"
echo "Example: $0 /Users/Shared MyImage /Users/username/Documents"
exit 1
fi
# Validate source folder exists
if [[ ! -d "$SOURCE_FOLDER" ]]; then
echo "❌ Source folder does not exist: $SOURCE_FOLDER"
exit 1
fi
# Create output directory if it doesn't exist
mkdir -p "$OUTPUT_PATH"
echo "💿 Creating disk image from folder..."
echo "Source: $SOURCE_FOLDER"
echo "Image name: $IMAGE_NAME"
echo "Output: $OUTPUT_PATH/$IMAGE_NAME.dmg"
# Create the disk image
if hdiutil create -fs HFS+ -srcfolder "$SOURCE_FOLDER" -volname "$IMAGE_NAME" "$OUTPUT_PATH/$IMAGE_NAME.dmg"; then
echo "✅ Disk image created successfully"
# Get image size
IMAGE_SIZE=$(du -h "$OUTPUT_PATH/$IMAGE_NAME.dmg" | cut -f1)
echo "Image size: $IMAGE_SIZE"
# Get source folder size for comparison
SOURCE_SIZE=$(du -sh "$SOURCE_FOLDER" | cut -f1)
echo "Source folder size: $SOURCE_SIZE"
else
echo "❌ Failed to create disk image"
exit 1
fi
Advanced Disk Image Creation
#!/bin/bash
# Advanced disk image creation with options
create_advanced_disk_image() {
local source_folder="$1"
local image_name="$2"
local output_path="$3"
local filesystem="${4:-HFS+}"
local compression="${5:-UDBZ}"
local encryption="${6:-false}"
if [[ ! -d "$source_folder" ]]; then
echo "❌ Source folder not found: $source_folder"
return 1
fi
mkdir -p "$output_path"
echo "💿 Creating advanced disk image..."
echo "Source: $source_folder"
echo "Filesystem: $filesystem"
echo "Compression: $compression"
echo "Encryption: $encryption"
# Build hdiutil command
local cmd="hdiutil create"
cmd="$cmd -fs $filesystem"
cmd="$cmd -srcfolder '$source_folder'"
cmd="$cmd -volname '$image_name'"
# Add compression if specified
if [[ "$compression" != "none" ]]; then
cmd="$cmd -format $compression"
fi
# Add encryption if requested
if [[ "$encryption" == "true" ]]; then
cmd="$cmd -encryption AES-256"
cmd="$cmd -stdinpass"
echo "🔐 Encryption enabled - you will be prompted for a password"
fi
cmd="$cmd '$output_path/$image_name.dmg'"
# Execute command
if [[ "$encryption" == "true" ]]; then
echo "Enter password for disk image encryption:"
read -s password
echo "$password" | eval "$cmd"
else
eval "$cmd"
fi
if [[ $? -eq 0 ]]; then
echo "✅ Advanced disk image created successfully"
# Display image information
echo ""
echo "=== Image Information ==="
hdiutil imageinfo "$output_path/$image_name.dmg" | grep -E "Format|Compressed|Encrypted|Checksum"
return 0
else
echo "❌ Failed to create disk image"
return 1
fi
}
# Usage examples
# create_advanced_disk_image "/Users/Shared" "SharedData" "/tmp" "HFS+" "UDBZ" "false"
# create_advanced_disk_image "/Applications/MyApp.app" "MyApp" "/tmp" "HFS+" "UDZO" "true"
Filesystem and Format Options
Supported Filesystems
#!/bin/bash
# Display available filesystem and format options
show_disk_image_options() {
echo "=== Available Filesystems ==="
echo "HFS+ - Mac OS Extended (default)"
echo "HFS+J - Mac OS Extended (Journaled)"
echo "HFSX - Mac OS Extended (Case-sensitive)"
echo "JHFS+X - Mac OS Extended (Case-sensitive, Journaled)"
echo "MS-DOS - FAT32 (compatible with Windows)"
echo "UDF - Universal Disk Format"
echo "APFS - Apple File System (macOS 10.13+)"
echo ""
echo "=== Image Format Options ==="
echo "UDRO - Read-only, smaller size"
echo "UDCO - ADC compressed (obsolete)"
echo "UDZO - zlib compressed (most common)"
echo "UDBZ - bzip2 compressed (better compression)"
echo "ULFO - lzfse compressed (macOS 10.11+)"
echo "ULMO - lzma compressed"
echo "UFBI - Entire device"
echo "SPARSE - Sparse image (grows as needed)"
echo "SPARSEBUNDLE - Sparse bundle (network friendly)"
echo ""
echo "=== Encryption Options ==="
echo "AES-128 - 128-bit AES encryption"
echo "AES-256 - 256-bit AES encryption (recommended)"
}
# Create disk image with specific options
create_custom_disk_image() {
local source="$1"
local name="$2"
local output="$3"
local fs="$4"
local format="$5"
local encrypt="$6"
echo "Creating custom disk image with:"
echo " Filesystem: $fs"
echo " Format: $format"
echo " Encryption: $encrypt"
local cmd="hdiutil create -fs '$fs' -format '$format'"
if [[ "$encrypt" != "none" ]]; then
cmd="$cmd -encryption '$encrypt' -stdinpass"
fi
cmd="$cmd -srcfolder '$source' -volname '$name' '$output/$name.dmg'"
if [[ "$encrypt" != "none" ]]; then
echo "Enter encryption password:"
read -s password
echo "$password" | eval "$cmd"
else
eval "$cmd"
fi
}
# Example usage
# show_disk_image_options
# create_custom_disk_image "/path/to/folder" "MyImage" "/output/path" "HFS+" "UDBZ" "AES-256"
Batch Disk Image Operations
Batch Image Creation
#!/bin/bash
# Batch create disk images from multiple folders
batch_create_disk_images() {
local base_path="$1"
local output_dir="$2"
local filesystem="${3:-HFS+}"
local format="${4:-UDBZ}"
if [[ ! -d "$base_path" ]]; then
echo "❌ Base path not found: $base_path"
return 1
fi
mkdir -p "$output_dir"
echo "🔄 Starting batch disk image creation..."
echo "Base path: $base_path"
echo "Output directory: $output_dir"
echo "Filesystem: $filesystem"
echo "Format: $format"
echo ""
local success_count=0
local failed_count=0
local total_size=0
# Process each subdirectory
find "$base_path" -type d -mindepth 1 -maxdepth 1 | while read -r folder; do
local folder_name=$(basename "$folder")
local image_path="$output_dir/${folder_name}.dmg"
echo "Processing: $folder_name"
# Skip if image already exists
if [[ -f "$image_path" ]]; then
echo " ⏭️ Image already exists, skipping"
continue
fi
# Create disk image
if hdiutil create -fs "$filesystem" -format "$format" \
-srcfolder "$folder" -volname "$folder_name" \
"$image_path" >/dev/null 2>&1; then
local size=$(du -h "$image_path" | cut -f1)
echo " ✅ Created successfully ($size)"
((success_count++))
# Add to total size calculation
local size_bytes=$(du -b "$image_path" | cut -f1)
total_size=$((total_size + size_bytes))
else
echo " ❌ Failed to create image"
((failed_count++))
fi
done
echo ""
echo "=== Batch Operation Summary ==="
echo "Successful: $success_count"
echo "Failed: $failed_count"
echo "Total size: $(numfmt --to=iec $total_size)"
}
# Usage example
# batch_create_disk_images "/Users/Shared/Projects" "/tmp/project_images" "HFS+" "UDBZ"
Image Verification and Analysis
#!/bin/bash
# Verify and analyze disk images
verify_disk_image() {
local image_path="$1"
if [[ ! -f "$image_path" ]]; then
echo "❌ Image file not found: $image_path"
return 1
fi
echo "🔍 Verifying disk image: $(basename "$image_path")"
# Basic image information
echo ""
echo "=== Basic Information ==="
echo "File size: $(du -h "$image_path" | cut -f1)"
echo "File type: $(file "$image_path" | cut -d: -f2- | xargs)"
# Detailed image information
echo ""
echo "=== Detailed Image Information ==="
hdiutil imageinfo "$image_path" | grep -E "Format|Partition|Compressed|Encrypted|Checksum|Total"
# Verify image integrity
echo ""
echo "=== Integrity Verification ==="
if hdiutil verify "$image_path" >/dev/null 2>&1; then
echo "✅ Image integrity verified successfully"
else
echo "❌ Image integrity verification failed"
return 1
fi
# Test mount capability
echo ""
echo "=== Mount Test ==="
local mount_point=$(mktemp -d)
if hdiutil attach "$image_path" -mountpoint "$mount_point" -nobrowse -quiet; then
echo "✅ Image mounts successfully"
# Get volume information
echo "Volume info: $(df -h "$mount_point" | tail -1 | awk '{print $2 " total, " $3 " used, " $4 " available"}')"
# Count contents
local file_count=$(find "$mount_point" -type f | wc -l | xargs)
local dir_count=$(find "$mount_point" -type d | wc -l | xargs)
echo "Contents: $file_count files, $dir_count directories"
# Unmount
hdiutil detach "$mount_point" -quiet
rmdir "$mount_point"
else
echo "❌ Image failed to mount"
rmdir "$mount_point"
return 1
fi
echo ""
echo "✅ Image verification completed successfully"
return 0
}
# Batch verification
verify_multiple_images() {
local image_dir="$1"
if [[ ! -d "$image_dir" ]]; then
echo "❌ Image directory not found: $image_dir"
return 1
fi
echo "🔍 Verifying all disk images in: $image_dir"
echo ""
local verified=0
local failed=0
find "$image_dir" -name "*.dmg" -type f | while read -r image; do
echo "Verifying: $(basename "$image")"
if verify_disk_image "$image" >/dev/null 2>&1; then
echo " ✅ Verified"
((verified++))
else
echo " ❌ Failed"
((failed++))
fi
done
echo ""
echo "Verification complete: $verified passed, $failed failed"
}
Enterprise Disk Image Management
#!/bin/bash
# MacFleet Disk Image Management Tool
# Comprehensive disk image creation and management for enterprise environments
# Configuration
LOG_FILE="/var/log/macfleet_diskimage.log"
BACKUP_DIR="/var/backups/macfleet/images"
REPORT_DIR="/var/reports/macfleet/images"
CONFIG_FILE="/etc/macfleet/image_policy.conf"
TEMP_DIR="/tmp/macfleet_images"
# Default settings
DEFAULT_FILESYSTEM="HFS+"
DEFAULT_FORMAT="UDBZ"
DEFAULT_ENCRYPTION="AES-256"
ENABLE_COMPRESSION=true
ENABLE_VERIFICATION=true
MAX_IMAGE_SIZE="10G"
CLEANUP_TEMP_FILES=true
# Logging function
log_action() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# Setup directories
setup_directories() {
for dir in "$BACKUP_DIR" "$REPORT_DIR" "$(dirname "$CONFIG_FILE")" "$TEMP_DIR"; do
if [[ ! -d "$dir" ]]; then
sudo mkdir -p "$dir"
log_action "Created directory: $dir"
fi
done
}
# Check available disk space
check_disk_space() {
local target_dir="$1"
local required_space="$2" # in bytes
local available_space=$(df "$target_dir" | tail -1 | awk '{print $4}')
available_space=$((available_space * 1024)) # Convert to bytes
if [[ "$available_space" -lt "$required_space" ]]; then
echo "❌ Insufficient disk space"
echo "Required: $(numfmt --to=iec $required_space)"
echo "Available: $(numfmt --to=iec $available_space)"
return 1
fi
return 0
}
# Create enterprise disk image with full logging and validation
create_enterprise_disk_image() {
local source_path="$1"
local image_name="$2"
local output_dir="$3"
local filesystem="${4:-$DEFAULT_FILESYSTEM}"
local format="${5:-$DEFAULT_FORMAT}"
local encrypt="${6:-false}"
local description="$7"
log_action "Starting enterprise disk image creation: $image_name"
# Validation
if [[ ! -d "$source_path" ]]; then
echo "❌ Source path not found: $source_path"
log_action "ERROR: Source path not found: $source_path"
return 1
fi
# Calculate source size
local source_size_bytes=$(du -sb "$source_path" | cut -f1)
local source_size_human=$(du -sh "$source_path" | cut -f1)
echo "📁 Source analysis:"
echo " Path: $source_path"
echo " Size: $source_size_human ($source_size_bytes bytes)"
# Check disk space (estimate 2x source size for safety)
local estimated_space=$((source_size_bytes * 2))
if ! check_disk_space "$output_dir" "$estimated_space"; then
log_action "ERROR: Insufficient disk space for image creation"
return 1
fi
# Create output directory
mkdir -p "$output_dir"
local output_path="$output_dir/$image_name.dmg"
local start_time=$(date +%s)
echo ""
echo "💿 Creating disk image..."
echo " Name: $image_name"
echo " Filesystem: $filesystem"
echo " Format: $format"
echo " Output: $output_path"
# Build command
local cmd="hdiutil create -fs '$filesystem' -format '$format'"
cmd="$cmd -srcfolder '$source_path' -volname '$image_name'"
# Add encryption if requested
if [[ "$encrypt" == "true" ]]; then
cmd="$cmd -encryption '$DEFAULT_ENCRYPTION' -stdinpass"
echo " Encryption: Enabled ($DEFAULT_ENCRYPTION)"
fi
cmd="$cmd '$output_path'"
# Execute image creation
local creation_success=false
if [[ "$encrypt" == "true" ]]; then
echo ""
echo "🔐 Enter password for disk image encryption:"
read -s password
if echo "$password" | eval "$cmd" >/dev/null 2>&1; then
creation_success=true
fi
else
if eval "$cmd" >/dev/null 2>&1; then
creation_success=true
fi
fi
local end_time=$(date +%s)
local duration=$((end_time - start_time))
if [[ "$creation_success" == "true" ]]; then
local image_size_bytes=$(du -b "$output_path" | cut -f1)
local image_size_human=$(du -h "$output_path" | cut -f1)
local compression_ratio=$(echo "scale=2; $image_size_bytes * 100 / $source_size_bytes" | bc)
echo ""
echo "✅ Disk image created successfully"
echo " Creation time: ${duration}s"
echo " Image size: $image_size_human"
echo " Compression ratio: ${compression_ratio}%"
# Verify image if enabled
if [[ "$ENABLE_VERIFICATION" == "true" ]]; then
echo ""
echo "🔍 Verifying image integrity..."
if hdiutil verify "$output_path" >/dev/null 2>&1; then
echo "✅ Image verification passed"
log_action "Image created and verified: $image_name ($image_size_human)"
else
echo "❌ Image verification failed"
log_action "ERROR: Image verification failed: $image_name"
return 1
fi
fi
# Generate image metadata
create_image_metadata "$output_path" "$source_path" "$description"
return 0
else
echo "❌ Failed to create disk image"
log_action "ERROR: Failed to create disk image: $image_name"
return 1
fi
}
# Create metadata file for the image
create_image_metadata() {
local image_path="$1"
local source_path="$2"
local description="$3"
local metadata_file="${image_path%.dmg}.json"
cat > "$metadata_file" << EOF
{
"image_name": "$(basename "$image_path")",
"creation_date": "$(date -Iseconds)",
"source_path": "$source_path",
"image_path": "$image_path",
"description": "$description",
"file_size": $(du -b "$image_path" | cut -f1),
"file_size_human": "$(du -h "$image_path" | cut -f1)",
"checksum_md5": "$(md5 -q "$image_path")",
"checksum_sha256": "$(shasum -a 256 "$image_path" | cut -d' ' -f1)",
"format_info": $(hdiutil imageinfo "$image_path" -plist | plutil -convert json -o - -)
}
EOF
echo "📄 Metadata saved: $metadata_file"
}
# Generate comprehensive image report
generate_image_report() {
local image_dir="${1:-$BACKUP_DIR}"
local report_file="$REPORT_DIR/image_report_$(date +%Y%m%d_%H%M%S).txt"
echo "📊 Generating disk image report..."
{
echo "MacFleet Disk Image Management Report"
echo "Generated: $(date)"
echo "Image Directory: $image_dir"
echo "======================================"
echo ""
if [[ ! -d "$image_dir" ]]; then
echo "❌ Image directory not found: $image_dir"
return 1
fi
# Count and analyze images
local total_images=$(find "$image_dir" -name "*.dmg" -type f | wc -l)
local total_size_bytes=0
local verified_count=0
local failed_count=0
echo "=== Summary ==="
echo "Total disk images: $total_images"
if [[ "$total_images" -eq 0 ]]; then
echo "No disk images found in directory"
return 0
fi
echo ""
echo "=== Image Details ==="
printf "%-30s %-10s %-15s %-10s\n" "Name" "Size" "Format" "Status"
printf "%-30s %-10s %-15s %-10s\n" "----" "----" "------" "------"
find "$image_dir" -name "*.dmg" -type f | sort | while read -r image_path; do
local image_name=$(basename "$image_path")
local image_size=$(du -h "$image_path" | cut -f1)
local image_size_bytes=$(du -b "$image_path" | cut -f1)
# Get format info
local format_info=$(hdiutil imageinfo "$image_path" 2>/dev/null | grep "Format Description" | cut -d: -f2- | xargs)
if [[ -z "$format_info" ]]; then
format_info="Unknown"
fi
# Verify integrity
local status="Unknown"
if hdiutil verify "$image_path" >/dev/null 2>&1; then
status="✅ Valid"
((verified_count++))
else
status="❌ Failed"
((failed_count++))
fi
printf "%-30s %-10s %-15s %-10s\n" "$image_name" "$image_size" "$format_info" "$status"
total_size_bytes=$((total_size_bytes + image_size_bytes))
done
echo ""
echo "=== Statistics ==="
echo "Total size: $(numfmt --to=iec $total_size_bytes)"
echo "Verified images: $verified_count"
echo "Failed verification: $failed_count"
echo "Average size: $(numfmt --to=iec $((total_size_bytes / total_images)))"
# Storage recommendations
echo ""
echo "=== Recommendations ==="
if [[ "$failed_count" -gt 0 ]]; then
echo "⚠️ $failed_count images failed verification - investigate and recreate"
fi
if [[ "$total_size_bytes" -gt $((50 * 1024 * 1024 * 1024)) ]]; then # 50GB
echo "💡 Consider archiving older images to free up space"
fi
echo "💡 Regular verification recommended for critical images"
} > "$report_file"
echo "📊 Report saved to: $report_file"
log_action "Image report generated: $report_file"
}
# Main execution function
main() {
local action="${1:-help}"
local source="${2:-}"
local name="${3:-}"
local output="${4:-$BACKUP_DIR}"
log_action "=== MacFleet Disk Image Management Started ==="
setup_directories
case "$action" in
"create")
if [[ -n "$source" && -n "$name" ]]; then
create_enterprise_disk_image "$source" "$name" "$output"
else
echo "❌ Usage: $0 create <source_folder> <image_name> [output_dir]"
echo "Example: $0 create /Users/Shared MyImage /tmp"
fi
;;
"batch")
if [[ -n "$source" ]]; then
batch_create_disk_images "$source" "$output"
else
echo "❌ Usage: $0 batch <base_folder> [output_dir]"
echo "Example: $0 batch /Users/Shared/Projects /tmp/images"
fi
;;
"verify")
if [[ -n "$source" ]]; then
if [[ -f "$source" ]]; then
verify_disk_image "$source"
elif [[ -d "$source" ]]; then
verify_multiple_images "$source"
else
echo "❌ Path not found: $source"
fi
else
echo "❌ Usage: $0 verify <image_file_or_directory>"
fi
;;
"report")
generate_image_report "$source"
;;
"info")
if [[ -n "$source" && -f "$source" ]]; then
echo "=== Image Information ==="
hdiutil imageinfo "$source"
else
echo "❌ Usage: $0 info <image_file>"
fi
;;
"options")
show_disk_image_options
;;
"help"|*)
echo "MacFleet Disk Image Management Tool"
echo "Usage: $0 [action] [options]"
echo ""
echo "Actions:"
echo " create <source> <name> [output] - Create disk image from folder"
echo " batch <base_dir> [output] - Create images from all subdirectories"
echo " verify <image_or_dir> - Verify image integrity"
echo " report [image_dir] - Generate comprehensive report"
echo " info <image_file> - Show detailed image information"
echo " options - Show available filesystem and format options"
echo " help - Show this help message"
echo ""
echo "Examples:"
echo " $0 create /Users/Shared MyData # Create MyData.dmg from /Users/Shared"
echo " $0 batch /Applications /tmp # Create images for all apps"
echo " $0 verify /tmp/MyData.dmg # Verify single image"
echo " $0 report /tmp # Generate report for all images in /tmp"
echo ""
echo "Configuration:"
echo " Default filesystem: $DEFAULT_FILESYSTEM"
echo " Default format: $DEFAULT_FORMAT"
echo " Default encryption: $DEFAULT_ENCRYPTION"
echo " Verification enabled: $ENABLE_VERIFICATION"
;;
esac
log_action "=== MacFleet Disk Image Management Completed ==="
}
# Execute main function
main "$@"
Image Format Comparison
Format | Compression | Size | Compatibility | Use Case |
---|---|---|---|---|
UDRO | None | Large | Universal | Testing, temporary images |
UDZO | zlib (good) | Medium | macOS 10.2+ | General purpose, good balance |
UDBZ | bzip2 (better) | Small | macOS 10.4+ | Archive storage, slower access |
ULFO | lzfse (fast) | Small | macOS 10.11+ | Modern systems, fast compression |
SPARSE | None | Variable | macOS | Growing images, development |
Security and Encryption
Encrypted Image Creation
# Create encrypted disk image with enterprise policies
create_secure_image() {
local source="$1"
local name="$2"
local output="$3"
local encryption_level="${4:-AES-256}"
echo "🔐 Creating encrypted disk image..."
echo "Encryption: $encryption_level"
# Generate secure password if not provided
if [[ -z "$IMAGE_PASSWORD" ]]; then
echo "Enter encryption password (or set IMAGE_PASSWORD environment variable):"
read -s IMAGE_PASSWORD
fi
echo "$IMAGE_PASSWORD" | hdiutil create \
-fs HFS+ \
-format UDBZ \
-encryption "$encryption_level" \
-stdinpass \
-srcfolder "$source" \
-volname "$name" \
"$output/$name.dmg"
if [[ $? -eq 0 ]]; then
echo "✅ Encrypted image created successfully"
echo "🔒 Image is protected with $encryption_level encryption"
else
echo "❌ Failed to create encrypted image"
return 1
fi
}
Important Notes
- Disk Space - Ensure sufficient space for image creation (2x source size recommended)
- Performance - Compression trades size for creation/access speed
- Security - Use AES-256 encryption for sensitive data
- Compatibility - Choose appropriate filesystem for target systems
- Verification - Always verify critical images after creation
- Enterprise Deployment - Test image mounting on target systems before bulk deployment