Tutorial

New updates and improvements to Macfleet.

Desktop Wallpaper Management on macOS

Implement enterprise-grade desktop wallpaper management across your MacFleet deployment with standardized branding policies, automated image deployment, and comprehensive compliance monitoring. This tutorial provides solutions for maintaining consistent corporate visual identity and brand presence.

Understanding macOS Desktop Wallpaper Management

macOS provides several methods for setting desktop wallpapers programmatically:

  • AppleScript via osascript - Cross-application scripting for Finder integration
  • System Preferences - Native configuration through System Database
  • Desktop Pictures Database - Direct SQLite database manipulation
  • Configuration Profiles - MDM-based wallpaper deployment
  • User Defaults - Per-user preference management

Basic Wallpaper Operations

Set Desktop Wallpaper

#!/bin/bash

# Basic wallpaper setting
path="$1"
osascript -e 'tell application "Finder" to set desktop picture to POSIX file "'"$path"'"'
ret=$?

if [ $ret == "0" ]; then
    echo "Wallpaper set successfully"
else
    echo "Operation failed."
fi

Enhanced Wallpaper Setting with Validation

#!/bin/bash

# Enhanced wallpaper setting with validation and error handling
set_wallpaper() {
    local image_path="$1"
    local user_name="$2"
    
    # Validate image file exists
    if [[ ! -f "$image_path" ]]; then
        echo "❌ Error: Image file not found: $image_path"
        return 1
    fi
    
    # Validate image format
    local file_type
    file_type=$(file --mime-type "$image_path" | awk '{print $2}')
    
    if [[ ! "$file_type" =~ ^image/ ]]; then
        echo "❌ Error: Invalid image format: $file_type"
        return 1
    fi
    
    # Set wallpaper using AppleScript
    echo "Setting wallpaper: $image_path"
    
    if [[ -n "$user_name" ]]; then
        # Set for specific user
        sudo -u "$user_name" osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$image_path\""
    else
        # Set for current user
        osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$image_path\""
    fi
    
    local result=$?
    
    if [[ $result -eq 0 ]]; then
        echo "✅ Wallpaper set successfully for ${user_name:-current user}"
        return 0
    else
        echo "❌ Failed to set wallpaper (exit code: $result)"
        return 1
    fi
}

# Usage example
# set_wallpaper "/Users/Admin/Pictures/company_wallpaper.png" "admin"

Enterprise Wallpaper Management System

Comprehensive Wallpaper Management Tool

#!/bin/bash

# MacFleet Enterprise Desktop Wallpaper Management Tool
# Centralized branding and wallpaper policy enforcement

# Configuration
CONFIG_FILE="/etc/macfleet/wallpaper_policy.conf"
LOG_FILE="/var/log/macfleet_wallpaper.log"
WALLPAPER_DIR="/Library/MacFleet/Wallpapers"
REPORT_DIR="/var/log/macfleet_reports"

# Create directories
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$WALLPAPER_DIR" "$REPORT_DIR"

# Default wallpaper policy
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# MacFleet Wallpaper Management Policy
# Version: 2.0

# Branding Configuration
ENFORCE_CORPORATE_BRANDING=true
ALLOW_USER_CUSTOMIZATION=false
DEFAULT_WALLPAPER="corporate_standard.jpg"
FALLBACK_WALLPAPER="macfleet_default.png"

# Wallpaper Repository
WALLPAPER_REPOSITORY_URL="https://assets.macfleet.com/wallpapers"
LOCAL_WALLPAPER_DIR="/Library/MacFleet/Wallpapers"
SYNC_WALLPAPERS=true

# Policy Settings
SCHEDULE_WALLPAPER_CHANGES=false
WALLPAPER_ROTATION_INTERVAL=86400  # 24 hours
VALIDATE_IMAGE_INTEGRITY=true
LOG_WALLPAPER_CHANGES=true

# User Restrictions
BLOCK_SYSTEM_PREFERENCES_DESKTOP=false
HIDE_DESKTOP_PREFERENCES=false
LOCK_WALLPAPER_SETTINGS=false

# Supported Formats
SUPPORTED_FORMATS="jpg,jpeg,png,heic,bmp,tiff,gif"
MAX_FILE_SIZE_MB=10
MIN_RESOLUTION="1024x768"
EOF

# Source configuration
source "$CONFIG_FILE" 2>/dev/null || true

# Logging function
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Validate image file
validate_image() {
    local image_path="$1"
    local errors=()
    
    # Check file existence
    if [[ ! -f "$image_path" ]]; then
        errors+=("File does not exist")
        printf '%s\n' "${errors[@]}"
        return 1
    fi
    
    # Check file format
    local file_type
    file_type=$(file --mime-type "$image_path" 2>/dev/null | awk '{print $2}')
    
    if [[ ! "$file_type" =~ ^image/ ]]; then
        errors+=("Invalid image format: $file_type")
    fi
    
    # Check file extension
    local extension
    extension=$(echo "${image_path##*.}" | tr '[:upper:]' '[:lower:]')
    
    if [[ ",$SUPPORTED_FORMATS," != *",$extension,"* ]]; then
        errors+=("Unsupported file format: $extension")
    fi
    
    # Check file size
    if command -v stat >/dev/null; then
        local file_size_mb
        file_size_mb=$(( $(stat -f%z "$image_path" 2>/dev/null || echo 0) / 1024 / 1024 ))
        
        if [[ $file_size_mb -gt $MAX_FILE_SIZE_MB ]]; then
            errors+=("File too large: ${file_size_mb}MB (max: ${MAX_FILE_SIZE_MB}MB)")
        fi
    fi
    
    # Check image dimensions
    if command -v sips >/dev/null; then
        local dimensions
        dimensions=$(sips -g pixelWidth -g pixelHeight "$image_path" 2>/dev/null | grep -E "pixelWidth|pixelHeight" | awk '{print $2}' | tr '\n' 'x' | sed 's/x$//')
        
        if [[ -n "$dimensions" ]]; then
            local width height
            width=$(echo "$dimensions" | cut -d'x' -f1)
            height=$(echo "$dimensions" | cut -d'x' -f2)
            local min_width min_height
            min_width=$(echo "$MIN_RESOLUTION" | cut -d'x' -f1)
            min_height=$(echo "$MIN_RESOLUTION" | cut -d'x' -f2)
            
            if [[ $width -lt $min_width || $height -lt $min_height ]]; then
                errors+=("Resolution too low: ${dimensions} (min: ${MIN_RESOLUTION})")
            fi
        fi
    fi
    
    if [[ ${#errors[@]} -eq 0 ]]; then
        return 0
    else
        printf '%s\n' "${errors[@]}"
        return 1
    fi
}

# Download wallpaper from repository
download_wallpaper() {
    local wallpaper_name="$1"
    local local_path="$WALLPAPER_DIR/$wallpaper_name"
    
    if [[ "$SYNC_WALLPAPERS" != "true" ]]; then
        echo "Wallpaper sync disabled"
        return 1
    fi
    
    echo "Downloading wallpaper: $wallpaper_name"
    
    # Download using curl
    if curl -fsSL "$WALLPAPER_REPOSITORY_URL/$wallpaper_name" -o "$local_path.tmp"; then
        # Validate downloaded image
        if validate_image "$local_path.tmp" >/dev/null 2>&1; then
            mv "$local_path.tmp" "$local_path"
            echo "✅ Downloaded and validated: $wallpaper_name"
            log_action "Downloaded wallpaper: $wallpaper_name"
            return 0
        else
            rm -f "$local_path.tmp"
            echo "❌ Downloaded file failed validation"
            return 1
        fi
    else
        echo "❌ Failed to download wallpaper"
        return 1
    fi
}

# Set wallpaper for user
set_user_wallpaper() {
    local image_path="$1"
    local target_user="$2"
    
    echo "=== Setting Wallpaper ==="
    echo "Image: $image_path"
    echo "User: ${target_user:-current user}"
    
    # Validate image
    if ! validate_image "$image_path"; then
        echo "❌ Image validation failed"
        return 1
    fi
    
    # Set wallpaper
    if [[ -n "$target_user" ]]; then
        # Set for specific user (requires appropriate permissions)
        sudo -u "$target_user" osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$image_path\"" 2>/dev/null
    else
        # Set for current user
        osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$image_path\""
    fi
    
    local result=$?
    
    if [[ $result -eq 0 ]]; then
        echo "✅ Wallpaper set successfully"
        log_action "Wallpaper set: $image_path for user: ${target_user:-current}"
        return 0
    else
        echo "❌ Failed to set wallpaper (exit code: $result)"
        log_action "FAILED to set wallpaper: $image_path for user: ${target_user:-current}"
        return 1
    fi
}

# Apply corporate wallpaper
apply_corporate_wallpaper() {
    local wallpaper_name="${1:-$DEFAULT_WALLPAPER}"
    local target_user="$2"
    
    echo "=== Applying Corporate Wallpaper ==="
    
    if [[ "$ENFORCE_CORPORATE_BRANDING" != "true" ]]; then
        echo "Corporate branding enforcement disabled"
        return 0
    fi
    
    # Check if wallpaper exists locally
    local wallpaper_path="$WALLPAPER_DIR/$wallpaper_name"
    
    if [[ ! -f "$wallpaper_path" ]]; then
        echo "Wallpaper not found locally, attempting download..."
        if ! download_wallpaper "$wallpaper_name"; then
            echo "Using fallback wallpaper..."
            wallpaper_path="$WALLPAPER_DIR/$FALLBACK_WALLPAPER"
            
            if [[ ! -f "$wallpaper_path" ]]; then
                echo "❌ No wallpaper available (including fallback)"
                return 1
            fi
        else
            wallpaper_path="$WALLPAPER_DIR/$wallpaper_name"
        fi
    fi
    
    # Apply wallpaper
    set_user_wallpaper "$wallpaper_path" "$target_user"
}

# Get current wallpaper information
get_current_wallpaper() {
    echo "=== Current Wallpaper Information ==="
    
    # Get current wallpaper path using AppleScript
    local current_wallpaper
    current_wallpaper=$(osascript -e 'tell application "Finder" to get desktop picture as string' 2>/dev/null)
    
    if [[ -n "$current_wallpaper" ]]; then
        # Convert from HFS+ path to POSIX path
        local posix_path
        posix_path=$(osascript -e "get POSIX path of \"$current_wallpaper\"" 2>/dev/null)
        
        echo "Current wallpaper: $posix_path"
        
        if [[ -f "$posix_path" ]]; then
            echo "File size: $(du -h "$posix_path" | cut -f1)"
            
            # Get image dimensions if sips is available
            if command -v sips >/dev/null; then
                local dimensions
                dimensions=$(sips -g pixelWidth -g pixelHeight "$posix_path" 2>/dev/null | grep -E "pixelWidth|pixelHeight" | awk '{print $2}' | tr '\n' 'x' | sed 's/x$//')
                echo "Dimensions: $dimensions"
            fi
            
            # Check if it's a corporate wallpaper
            if [[ "$posix_path" == "$WALLPAPER_DIR"* ]]; then
                echo "✅ Corporate wallpaper detected"
            else
                echo "⚠️  Non-corporate wallpaper detected"
            fi
        else
            echo "⚠️  Wallpaper file not found"
        fi
    else
        echo "❌ Unable to retrieve current wallpaper"
    fi
}

# Sync wallpaper repository
sync_wallpaper_repository() {
    echo "=== Syncing Wallpaper Repository ==="
    
    if [[ "$SYNC_WALLPAPERS" != "true" ]]; then
        echo "Wallpaper sync disabled"
        return 0
    fi
    
    # Create wallpaper directory
    mkdir -p "$WALLPAPER_DIR"
    
    # Download manifest file
    local manifest_file="$WALLPAPER_DIR/.manifest"
    
    if curl -fsSL "$WALLPAPER_REPOSITORY_URL/manifest.txt" -o "$manifest_file.tmp" 2>/dev/null; then
        echo "Downloaded wallpaper manifest"
        
        # Process manifest and download wallpapers
        while IFS= read -r wallpaper_name; do
            [[ -z "$wallpaper_name" || "$wallpaper_name" =~ ^# ]] && continue
            
            local local_path="$WALLPAPER_DIR/$wallpaper_name"
            
            if [[ ! -f "$local_path" ]]; then
                echo "Downloading: $wallpaper_name"
                download_wallpaper "$wallpaper_name"
            else
                echo "Already exists: $wallpaper_name"
            fi
        done < "$manifest_file.tmp"
        
        mv "$manifest_file.tmp" "$manifest_file"
        echo "✅ Wallpaper repository synchronized"
        log_action "Wallpaper repository synchronized"
    else
        echo "❌ Failed to download manifest"
        return 1
    fi
}

# Generate compliance report
generate_wallpaper_report() {
    local report_file="$REPORT_DIR/wallpaper_compliance_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Wallpaper Compliance Report ==="
    
    # Get current wallpaper
    local current_wallpaper
    current_wallpaper=$(osascript -e 'tell application "Finder" to get desktop picture as string' 2>/dev/null)
    local posix_path=""
    local is_corporate="false"
    local compliance_status="non_compliant"
    
    if [[ -n "$current_wallpaper" ]]; then
        posix_path=$(osascript -e "get POSIX path of \"$current_wallpaper\"" 2>/dev/null)
        
        if [[ "$posix_path" == "$WALLPAPER_DIR"* ]]; then
            is_corporate="true"
            compliance_status="compliant"
        fi
    fi
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "wallpaper_compliance",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)",
    "macos_version": "$(sw_vers -productVersion)",
    "current_user": "$(whoami)"
  },
  "wallpaper_status": {
    "current_wallpaper": "$posix_path",
    "is_corporate_wallpaper": $is_corporate,
    "compliance_status": "$compliance_status",
    "branding_enforced": $ENFORCE_CORPORATE_BRANDING
  },
  "policy_settings": {
    "corporate_branding_enforced": $ENFORCE_CORPORATE_BRANDING,
    "user_customization_allowed": $ALLOW_USER_CUSTOMIZATION,
    "default_wallpaper": "$DEFAULT_WALLPAPER",
    "wallpaper_sync_enabled": $SYNC_WALLPAPERS
  },
  "repository_info": {
    "local_wallpaper_count": $(find "$WALLPAPER_DIR" -name "*.jpg" -o -name "*.png" -o -name "*.jpeg" 2>/dev/null | wc -l | xargs),
    "last_sync": "$(stat -f %Sm "$WALLPAPER_DIR/.manifest" 2>/dev/null || echo "never")"
  }
}
EOF
    
    echo "Wallpaper compliance report saved to: $report_file"
    log_action "Wallpaper compliance report generated: $report_file"
}

# Main function with argument handling
main() {
    log_action "=== MacFleet Wallpaper Management Tool Started ==="
    
    case "${1:-status}" in
        "set")
            set_user_wallpaper "$2" "$3"
            ;;
        "corporate")
            apply_corporate_wallpaper "$2" "$3"
            ;;
        "sync")
            sync_wallpaper_repository
            ;;
        "validate")
            if validate_image "$2"; then
                echo "✅ Image validation passed: $2"
            else
                echo "❌ Image validation failed: $2"
            fi
            ;;
        "download")
            download_wallpaper "$2"
            ;;
        "report")
            generate_wallpaper_report
            ;;
        "status"|*)
            get_current_wallpaper
            ;;
    esac
    
    log_action "=== Wallpaper management operation completed ==="
}

# Execute main function
main "$@"

Advanced Wallpaper Management

Automated Wallpaper Rotation

#!/bin/bash

# Automated wallpaper rotation system
setup_wallpaper_rotation() {
    echo "=== Setting Up Wallpaper Rotation ==="
    
    if [[ "$SCHEDULE_WALLPAPER_CHANGES" != "true" ]]; then
        echo "Wallpaper rotation disabled in policy"
        return 0
    fi
    
    # Create rotation script
    local rotation_script="/usr/local/bin/macfleet-wallpaper-rotate"
    
    cat > "$rotation_script" << 'EOF'
#!/bin/bash
# MacFleet Wallpaper Rotation Script

WALLPAPER_DIR="/Library/MacFleet/Wallpapers"
LOG_FILE="/var/log/macfleet_wallpaper.log"

# Get list of available wallpapers
mapfile -t wallpapers < <(find "$WALLPAPER_DIR" -name "*.jpg" -o -name "*.png" -o -name "*.jpeg" 2>/dev/null)

if [[ ${#wallpapers[@]} -eq 0 ]]; then
    echo "$(date) - No wallpapers found for rotation" >> "$LOG_FILE"
    exit 1
fi

# Select random wallpaper
random_wallpaper="${wallpapers[$RANDOM % ${#wallpapers[@]}]}"

# Apply wallpaper
/usr/local/bin/macfleet-wallpaper set "$random_wallpaper"

echo "$(date) - Rotated to wallpaper: $random_wallpaper" >> "$LOG_FILE"
EOF
    
    chmod +x "$rotation_script"
    
    # Create LaunchDaemon for scheduling
    local plist_file="/Library/LaunchDaemons/com.macfleet.wallpaper-rotation.plist"
    
    cat > "$plist_file" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.macfleet.wallpaper-rotation</string>
    <key>ProgramArguments</key>
    <array>
        <string>$rotation_script</string>
    </array>
    <key>StartInterval</key>
    <integer>$WALLPAPER_ROTATION_INTERVAL</integer>
    <key>RunAtLoad</key>
    <false/>
</dict>
</plist>
EOF
    
    # Load the daemon
    launchctl load "$plist_file"
    
    echo "✅ Wallpaper rotation configured (interval: ${WALLPAPER_ROTATION_INTERVAL}s)"
}

setup_wallpaper_rotation

Multi-Display Wallpaper Management

#!/bin/bash

# Multi-display wallpaper management
set_multi_display_wallpapers() {
    echo "=== Multi-Display Wallpaper Management ==="
    
    # Get display count
    local display_count
    display_count=$(system_profiler SPDisplaysDataType | grep -c "Resolution:")
    
    echo "Detected displays: $display_count"
    
    if [[ $display_count -gt 1 ]]; then
        echo "Setting wallpapers for multiple displays..."
        
        # Set different wallpapers for each display
        for ((i=1; i<=display_count; i++)); do
            local wallpaper_file="display_${i}_wallpaper.jpg"
            local wallpaper_path="$WALLPAPER_DIR/$wallpaper_file"
            
            if [[ -f "$wallpaper_path" ]]; then
                echo "Setting wallpaper for display $i: $wallpaper_file"
                
                # Use AppleScript to set wallpaper for specific display
                osascript << EOF
                tell application "System Events"
                    tell desktop $i
                        set picture to "$wallpaper_path"
                    end tell
                end tell
EOF
            else
                echo "⚠️  Wallpaper not found for display $i: $wallpaper_file"
            fi
        done
    else
        echo "Single display detected, using standard wallpaper"
        apply_corporate_wallpaper
    fi
}

set_multi_display_wallpapers

Wallpaper Policy Enforcement

#!/bin/bash

# Monitor and enforce wallpaper policies
monitor_wallpaper_compliance() {
    echo "=== Wallpaper Compliance Monitoring ==="
    
    # Check current wallpaper compliance
    local current_wallpaper
    current_wallpaper=$(osascript -e 'tell application "Finder" to get desktop picture as string' 2>/dev/null)
    
    if [[ -n "$current_wallpaper" ]]; then
        local posix_path
        posix_path=$(osascript -e "get POSIX path of \"$current_wallpaper\"" 2>/dev/null)
        
        # Check if wallpaper is from corporate repository
        if [[ "$posix_path" != "$WALLPAPER_DIR"* ]] && [[ "$ENFORCE_CORPORATE_BRANDING" == "true" ]]; then
            echo "⚠️  Non-corporate wallpaper detected: $posix_path"
            log_action "POLICY VIOLATION: Non-corporate wallpaper detected: $posix_path"
            
            # Auto-remediate if enabled
            if [[ "$ALLOW_USER_CUSTOMIZATION" != "true" ]]; then
                echo "Auto-remediating with corporate wallpaper..."
                apply_corporate_wallpaper
                log_action "Auto-remediated wallpaper policy violation"
            fi
        else
            echo "✅ Wallpaper compliance: OK"
        fi
    else
        echo "❌ Unable to check wallpaper compliance"
    fi
}

monitor_wallpaper_compliance

Integration and Deployment

MDM Integration Script

#!/bin/bash

# MDM integration for wallpaper deployment
deploy_wallpaper_via_mdm() {
    local wallpaper_url="$1"
    local deployment_mode="${2:-immediate}"
    
    echo "=== MDM Wallpaper Deployment ==="
    echo "Source: $wallpaper_url"
    echo "Mode: $deployment_mode"
    
    # Download wallpaper
    local temp_file="/tmp/mdm_wallpaper_$(date +%s).jpg"
    
    if curl -fsSL "$wallpaper_url" -o "$temp_file"; then
        echo "✅ Downloaded wallpaper from MDM"
        
        # Validate and deploy
        if validate_image "$temp_file"; then
            # Copy to corporate wallpaper directory
            local dest_file="$WALLPAPER_DIR/mdm_deployed_$(basename "$temp_file")"
            cp "$temp_file" "$dest_file"
            
            # Apply immediately or schedule
            case "$deployment_mode" in
                "immediate")
                    set_user_wallpaper "$dest_file"
                    ;;
                "next_login")
                    # Set as default for next login
                    defaults write /Library/Preferences/com.apple.desktop Background "{default = {ImageFilePath = '$dest_file'; }; }"
                    ;;
                "scheduled")
                    # Add to rotation pool
                    echo "Added to rotation pool: $dest_file"
                    ;;
            esac
            
            # Cleanup
            rm -f "$temp_file"
            echo "✅ MDM wallpaper deployment completed"
        else
            echo "❌ MDM wallpaper validation failed"
            rm -f "$temp_file"
            return 1
        fi
    else
        echo "❌ Failed to download wallpaper from MDM"
        return 1
    fi
}

# Example usage:
# deploy_wallpaper_via_mdm "https://mdm.company.com/wallpapers/quarterly_branding.jpg" "immediate"

Important Configuration Notes

AppleScript and Security

  • Privacy permissions required for script execution
  • User consent needed for Finder access on first run
  • Automation permissions for System Events access
  • Full Disk Access may be required for some operations

Supported Image Formats

  • JPEG/JPG - Most common, good compression
  • PNG - Supports transparency, larger files
  • HEIC - Apple's modern format, efficient
  • TIFF/BMP - Legacy formats, large files
  • GIF - Animated support (single frame used)

Best Practices for Enterprise

  1. Image Optimization

    • Use appropriate resolution for target displays
    • Optimize file sizes for network deployment
    • Test images across different display configurations
  2. Branding Consistency

    • Maintain corporate color schemes
    • Include company logos and messaging
    • Consider seasonal or campaign-specific variations
  3. Deployment Strategy

    • Use centralized image repositories
    • Implement staged rollouts for new wallpapers
    • Provide fallback options for connectivity issues
  4. User Experience

    • Consider user preferences where policy allows
    • Provide clear communication about branding policies
    • Offer opt-out mechanisms for non-critical branding

Troubleshooting Common Issues

  • Permission denied errors - Check script execution permissions and user context
  • Image not displaying - Verify file format compatibility and path accessibility
  • Policy conflicts - Review configuration profile settings and user defaults
  • Performance issues - Optimize image file sizes and deployment timing

Remember to test wallpaper changes across different display configurations and user scenarios before deploying to your entire MacFleet environment.

Deploy ZIP Files to Macs Using URLs

Deploying applications and files across your MacFleet can be streamlined by hosting ZIP files on a server and automatically downloading them to target devices. This tutorial shows how to create robust scripts for ZIP file deployment using URLs.

Understanding the Process

The deployment process involves:

  1. Download - Fetch the ZIP file from a URL using curl
  2. Extract - Unzip the contents using unzip
  3. Install - Optionally install or move files to their final location
  4. Cleanup - Remove temporary files

Basic ZIP Deployment Script

Simple Download and Extract

#!/bin/bash

# Basic ZIP deployment script
cd /tmp

# Download the ZIP file
curl -k https://example.com/myapp.zip -o "myapp.zip"

# Extract the contents
unzip "myapp.zip"

Enhanced Enterprise Script

For production environments with error handling and logging:

#!/bin/bash

# ZIP File Deployment Script for MacFleet
# Compatible with macOS 10.14+

# Configuration variables
DOWNLOAD_URL="$1"  # First argument: URL to ZIP file
ZIP_NAME="$2"      # Second argument: ZIP filename
DESTINATION="${3:-/tmp}"  # Third argument: destination (default: /tmp)
LOG_FILE="/var/log/zip_deployment.log"

# Function to log messages
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Function to validate URL
validate_url() {
    local url="$1"
    if [[ ! "$url" =~ ^https?:// ]]; then
        log_message "✗ Invalid URL format: $url"
        return 1
    fi
    return 0
}

# Function to check internet connectivity
check_connectivity() {
    if ! ping -c 1 google.com &> /dev/null; then
        log_message "✗ No internet connectivity"
        return 1
    fi
    return 0
}

# Function to download ZIP file
download_zip() {
    local url="$1"
    local filename="$2"
    local destination="$3"
    
    log_message "Starting download from: $url"
    
    # Create destination directory if it doesn't exist
    mkdir -p "$destination"
    cd "$destination" || return 1
    
    # Download with progress and error handling
    if curl -L --fail --connect-timeout 30 --max-time 300 \
            --progress-bar "$url" -o "$filename"; then
        log_message "✓ Download completed: $filename"
        return 0
    else
        log_message "✗ Download failed from: $url"
        return 1
    fi
}

# Function to extract ZIP file
extract_zip() {
    local filename="$1"
    local destination="$2"
    
    cd "$destination" || return 1
    
    # Check if ZIP file exists
    if [[ ! -f "$filename" ]]; then
        log_message "✗ ZIP file not found: $filename"
        return 1
    fi
    
    # Test ZIP integrity
    if ! unzip -t "$filename" &> /dev/null; then
        log_message "✗ ZIP file is corrupted: $filename"
        return 1
    fi
    
    # Extract files
    if unzip -o "$filename"; then
        log_message "✓ Extraction completed: $filename"
        return 0
    else
        log_message "✗ Extraction failed: $filename"
        return 1
    fi
}

# Function to install application (if .app bundle found)
install_application() {
    local source_dir="$1"
    
    # Look for .app bundles
    local app_bundle
    app_bundle=$(find "$source_dir" -name "*.app" -type d | head -1)
    
    if [[ -n "$app_bundle" ]]; then
        local app_name
        app_name=$(basename "$app_bundle")
        
        log_message "Found application bundle: $app_name"
        
        # Copy to Applications folder
        if cp -R "$app_bundle" "/Applications/"; then
            log_message "✓ Application installed: $app_name"
            return 0
        else
            log_message "✗ Application installation failed: $app_name"
            return 1
        fi
    else
        log_message "! No application bundle found for installation"
        return 0
    fi
}

# Function to cleanup temporary files
cleanup() {
    local destination="$1"
    local filename="$2"
    
    cd "$destination" || return 1
    
    if [[ -f "$filename" ]]; then
        rm -f "$filename"
        log_message "✓ Cleanup completed: $filename"
    fi
}

# Main deployment function
deploy_zip() {
    log_message "=== Starting ZIP deployment ==="
    
    # Validate inputs
    if [[ -z "$DOWNLOAD_URL" ]] || [[ -z "$ZIP_NAME" ]]; then
        log_message "✗ Usage: $0 <download_url> <zip_filename> [destination]"
        return 1
    fi
    
    # Validate URL format
    if ! validate_url "$DOWNLOAD_URL"; then
        return 1
    fi
    
    # Check connectivity
    if ! check_connectivity; then
        return 1
    fi
    
    # Download ZIP file
    if ! download_zip "$DOWNLOAD_URL" "$ZIP_NAME" "$DESTINATION"; then
        return 1
    fi
    
    # Extract ZIP file
    if ! extract_zip "$ZIP_NAME" "$DESTINATION"; then
        return 1
    fi
    
    # Attempt application installation
    install_application "$DESTINATION"
    
    # Cleanup temporary ZIP file
    cleanup "$DESTINATION" "$ZIP_NAME"
    
    log_message "=== ZIP deployment completed successfully ==="
    return 0
}

# Execute main function
if deploy_zip; then
    exit 0
else
    log_message "=== ZIP deployment failed ==="
    exit 1
fi

Quick Deployment Scripts

Download to Applications

#!/bin/bash

# Download and install app directly to Applications
URL="https://example.com/MyApp.zip"
ZIP_NAME="MyApp.zip"

cd /tmp
curl -L "$URL" -o "$ZIP_NAME"
unzip "$ZIP_NAME"

# Find and move .app bundle
APP_BUNDLE=$(find . -name "*.app" -type d | head -1)
if [[ -n "$APP_BUNDLE" ]]; then
    cp -R "$APP_BUNDLE" /Applications/
    echo "Application installed successfully"
fi

# Cleanup
rm -f "$ZIP_NAME"
rm -rf "${ZIP_NAME%.zip}"

Download with Checksum Verification

#!/bin/bash

URL="https://example.com/myapp.zip"
ZIP_NAME="myapp.zip"
EXPECTED_SHA256="abc123..."  # Replace with actual checksum

cd /tmp
curl -L "$URL" -o "$ZIP_NAME"

# Verify checksum
if echo "$EXPECTED_SHA256  $ZIP_NAME" | shasum -a 256 -c; then
    echo "Checksum verified"
    unzip "$ZIP_NAME"
else
    echo "Checksum verification failed"
    exit 1
fi

Usage Examples

Command Line Usage

# Basic usage
./deploy_zip.sh "https://example.com/app.zip" "app.zip"

# Custom destination
./deploy_zip.sh "https://example.com/app.zip" "app.zip" "/Applications"

# With logging
./deploy_zip.sh "https://example.com/app.zip" "app.zip" 2>&1 | tee deployment.log

MacFleet Deployment

#!/bin/bash

# Deploy multiple applications
APPS=(
    "https://cdn.example.com/productivity.zip:productivity.zip"
    "https://cdn.example.com/security.zip:security.zip"
    "https://cdn.example.com/utilities.zip:utilities.zip"
)

for app in "${APPS[@]}"; do
    IFS=':' read -r url filename <<< "$app"
    echo "Deploying: $filename"
    ./deploy_zip.sh "$url" "$filename"
done

Troubleshooting

IssueSolution
Download failsCheck URL accessibility and internet connection
ZIP extraction errorsVerify ZIP file integrity with unzip -t
Permission deniedRun script with admin privileges
App not installingCheck for .app bundle in extracted contents
Slow downloadsIncrease curl timeout values

Security Considerations

  • HTTPS URLs - Always use secure connections when possible
  • Checksum verification - Verify file integrity before extraction
  • Code signing - Verify application signatures before installation
  • Sandboxed downloads - Use /tmp for temporary storage

File Location Reference

  • Temporary files: /tmp/
  • Applications: /Applications/
  • User applications: ~/Applications/
  • System utilities: /usr/local/bin/
  • Logs: /var/log/zip_deployment.log

Advanced Features

Progress Monitoring

# Show download progress
curl --progress-bar -L "$URL" -o "$ZIP_NAME"

# Or with detailed progress
curl -# -L "$URL" -o "$ZIP_NAME"

Retry Logic

# Retry download up to 3 times
for i in {1..3}; do
    if curl -L "$URL" -o "$ZIP_NAME"; then
        break
    elif [[ $i -eq 3 ]]; then
        echo "Download failed after 3 attempts"
        exit 1
    fi
    sleep 5
done

Important Notes

  • ZIP files are temporarily stored in /tmp by default
  • Use secure HTTPS URLs when possible
  • Test scripts on a small group before enterprise deployment
  • Monitor disk space when deploying large files
  • Consider bandwidth limitations in your network

Delete Mobile Accounts on macOS Devices

This comprehensive guide demonstrates how to delete mobile accounts on macOS devices for effective user management, device reassignment, and organizational cleanup scenarios.

Overview

Mobile accounts on macOS are user profiles designed for seamless access to resources across different devices within organizations. Unlike local accounts, mobile accounts are centrally managed by directory services like Open Directory or Active Directory, enabling administrators to control access, enforce policies, and manage user data centrally.

Common Scenarios for Mobile Account Deletion

  • Employee departures: Clean up accounts when employees leave the organization
  • Role changes: Remove old mobile accounts when users change positions
  • Device reassignment: Prepare devices for new users
  • Security compliance: Remove inactive or compromised accounts
  • Storage optimization: Free up disk space by removing unused accounts
  • Organizational restructuring: Clean up accounts during company changes

Basic Mobile Account Deletion

Simple Mobile Account Removal Script

Create a basic script to remove all mobile accounts from a macOS device:

#!/bin/bash

# Basic mobile account deletion script
# Usage: ./delete_mobile_accounts.sh

delete_mobile_accounts() {
    echo "Starting mobile account deletion process..."
    
    # Check if running as root
    if [ "$EUID" -ne 0 ]; then
        echo "Error: This script must be run as root"
        exit 1
    fi
    
    # Counter for deleted accounts
    local deleted_count=0
    
    # Loop through all users
    for username in $(dscl . -list /Users | grep -v '^_'); do
        # Check if user has mobile account authentication
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            echo "Removing mobile account: $username"
            
            # Delete user from directory services
            dscl . -delete "/Users/$username"
            
            # Remove user's home directory
            rm -rf "/Users/$username"
            
            ((deleted_count++))
        fi
    done
    
    echo "Mobile accounts removal complete. Deleted $deleted_count accounts."
    echo "Note: Please restart the device for changes to take full effect."
}

# Execute deletion
delete_mobile_accounts

Enhanced Mobile Account Management Script

#!/bin/bash

# Enhanced mobile account management with safety checks and logging
# Usage: ./enhanced_mobile_account_manager.sh

enhanced_mobile_account_manager() {
    local log_file="/var/log/macfleet_mobile_accounts.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local backup_dir="/var/backups/macfleet/mobile_accounts"
    
    # Check if running as root
    if [ "$EUID" -ne 0 ]; then
        echo "Error: This script must be run as root"
        exit 1
    fi
    
    # Create log directory
    mkdir -p /var/log
    mkdir -p "$backup_dir"
    
    echo "[$timestamp] Enhanced mobile account manager started" >> "$log_file"
    
    # Display current mobile accounts
    display_mobile_accounts
    
    # Confirm deletion
    echo ""
    read -p "Do you want to proceed with mobile account deletion? (y/N): " confirm
    
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        create_account_backup
        delete_mobile_accounts_enhanced
    else
        echo "Operation cancelled."
        echo "[$timestamp] Mobile account deletion cancelled by user" >> "$log_file"
    fi
}

display_mobile_accounts() {
    echo "======================================="
    echo "Current Mobile Accounts on Device"
    echo "======================================="
    
    local mobile_accounts_found=false
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            mobile_accounts_found=true
            
            # Get additional user information
            local real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | cut -d: -f2 | xargs)
            local uid=$(dscl . -read "/Users/$username" UniqueID 2>/dev/null | cut -d: -f2 | xargs)
            local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
            local last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $3, $4, $5, $6}')
            
            echo "Username: $username"
            echo "  Real Name: $real_name"
            echo "  UID: $uid"
            echo "  Home Directory: $home_dir"
            echo "  Last Login: $last_login"
            
            # Check home directory size
            if [ -d "$home_dir" ]; then
                local dir_size=$(du -sh "$home_dir" 2>/dev/null | cut -f1)
                echo "  Home Directory Size: $dir_size"
            fi
            
            echo ""
        fi
    done
    
    if [ "$mobile_accounts_found" = false ]; then
        echo "No mobile accounts found on this device."
        echo "[$timestamp] No mobile accounts found on device" >> "$log_file"
        exit 0
    fi
}

create_account_backup() {
    echo "Creating backup of mobile account information..."
    
    local backup_file="$backup_dir/mobile_accounts_backup_$(date +%Y%m%d_%H%M%S).txt"
    
    cat > "$backup_file" << EOF
MacFleet Mobile Account Backup
Generated: $(date)
Device: $(scutil --get ComputerName)
macOS Version: $(sw_vers -productVersion)

Mobile Accounts Found:
EOF
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            echo "Username: $username" >> "$backup_file"
            dscl . -read "/Users/$username" >> "$backup_file"
            echo "---" >> "$backup_file"
        fi
    done
    
    echo "Backup created: $backup_file"
    echo "[$timestamp] Mobile account backup created: $backup_file" >> "$log_file"
}

delete_mobile_accounts_enhanced() {
    echo "======================================="
    echo "Deleting Mobile Accounts"
    echo "======================================="
    
    local deleted_count=0
    local failed_count=0
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            echo "Processing mobile account: $username"
            
            # Check if user is currently logged in
            if who | grep -q "^$username "; then
                echo "  Warning: User $username is currently logged in. Skipping..."
                echo "[$timestamp] Skipped deletion of $username - user currently logged in" >> "$log_file"
                ((failed_count++))
                continue
            fi
            
            # Delete user from directory services
            if dscl . -delete "/Users/$username" 2>/dev/null; then
                echo "  Deleted user record from directory services"
            else
                echo "  Warning: Failed to delete user record from directory services"
                echo "[$timestamp] Failed to delete user record for $username" >> "$log_file"
                ((failed_count++))
                continue
            fi
            
            # Remove user's home directory
            local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
            if [ -d "$home_dir" ]; then
                if rm -rf "$home_dir" 2>/dev/null; then
                    echo "  Removed home directory: $home_dir"
                else
                    echo "  Warning: Failed to remove home directory: $home_dir"
                    echo "[$timestamp] Failed to remove home directory for $username: $home_dir" >> "$log_file"
                fi
            fi
            
            echo "  Successfully deleted mobile account: $username"
            echo "[$timestamp] Successfully deleted mobile account: $username" >> "$log_file"
            ((deleted_count++))
        fi
    done
    
    echo ""
    echo "======================================="
    echo "Mobile Account Deletion Summary"
    echo "======================================="
    echo "Successfully deleted: $deleted_count accounts"
    echo "Failed to delete: $failed_count accounts"
    echo "Total processed: $((deleted_count + failed_count)) accounts"
    echo ""
    echo "Note: Please restart the device for changes to take full effect."
    
    echo "[$timestamp] Mobile account deletion completed - Success: $deleted_count, Failed: $failed_count" >> "$log_file"
}

# Execute enhanced management
enhanced_mobile_account_manager

Advanced Mobile Account Management

Selective Mobile Account Management

#!/bin/bash

# Selective mobile account management system
# Usage: ./selective_mobile_account_manager.sh

selective_mobile_account_manager() {
    local log_file="/var/log/macfleet_selective_mobile_accounts.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # Check if running as root
    if [ "$EUID" -ne 0 ]; then
        echo "Error: This script must be run as root"
        exit 1
    fi
    
    echo "[$timestamp] Selective mobile account manager started" >> "$log_file"
    
    while true; do
        display_selective_menu
        read -p "Select an option (1-7): " choice
        
        case $choice in
            1)
                list_mobile_accounts_detailed
                ;;
            2)
                delete_specific_mobile_account
                ;;
            3)
                delete_inactive_mobile_accounts
                ;;
            4)
                delete_mobile_accounts_by_criteria
                ;;
            5)
                export_mobile_account_report
                ;;
            6)
                restore_mobile_account_backup
                ;;
            7)
                echo "Exiting selective mobile account manager."
                exit 0
                ;;
            *)
                echo "Invalid option. Please try again."
                ;;
        esac
        
        echo ""
        read -p "Press Enter to continue..."
    done
}

display_selective_menu() {
    clear
    echo "======================================="
    echo "MacFleet Selective Mobile Account Manager"
    echo "======================================="
    echo ""
    echo "1. List all mobile accounts with details"
    echo "2. Delete specific mobile account"
    echo "3. Delete inactive mobile accounts"
    echo "4. Delete mobile accounts by criteria"
    echo "5. Export mobile account report"
    echo "6. Restore from backup"
    echo "7. Exit"
    echo ""
}

list_mobile_accounts_detailed() {
    echo "======================================="
    echo "Detailed Mobile Account Information"
    echo "======================================="
    
    local mobile_accounts=()
    local count=0
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            mobile_accounts+=("$username")
            ((count++))
            
            echo "[$count] Mobile Account: $username"
            
            # Get detailed information
            local real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | cut -d: -f2 | xargs)
            local uid=$(dscl . -read "/Users/$username" UniqueID 2>/dev/null | cut -d: -f2 | xargs)
            local gid=$(dscl . -read "/Users/$username" PrimaryGroupID 2>/dev/null | cut -d: -f2 | xargs)
            local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
            local shell=$(dscl . -read "/Users/$username" UserShell 2>/dev/null | cut -d: -f2 | xargs)
            
            echo "    Real Name: $real_name"
            echo "    UID: $uid"
            echo "    GID: $gid"
            echo "    Home Directory: $home_dir"
            echo "    Shell: $shell"
            
            # Check if user is currently logged in
            if who | grep -q "^$username "; then
                echo "    Status: Currently logged in"
            else
                echo "    Status: Not logged in"
            fi
            
            # Get last login information
            local last_login=$(last -1 "$username" 2>/dev/null | head -1)
            if [ -n "$last_login" ]; then
                echo "    Last Login: $last_login"
            else
                echo "    Last Login: Never"
            fi
            
            # Check home directory size
            if [ -d "$home_dir" ]; then
                local dir_size=$(du -sh "$home_dir" 2>/dev/null | cut -f1)
                echo "    Home Directory Size: $dir_size"
                
                # Check last modification time
                local last_modified=$(stat -f "%Sm" "$home_dir" 2>/dev/null)
                echo "    Last Modified: $last_modified"
            else
                echo "    Home Directory: Not found"
            fi
            
            echo ""
        fi
    done
    
    if [ $count -eq 0 ]; then
        echo "No mobile accounts found on this device."
    else
        echo "Total mobile accounts found: $count"
    fi
}

delete_specific_mobile_account() {
    echo "======================================="
    echo "Delete Specific Mobile Account"
    echo "======================================="
    
    # List mobile accounts with numbers
    local mobile_accounts=()
    local count=0
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            mobile_accounts+=("$username")
            ((count++))
            echo "[$count] $username"
        fi
    done
    
    if [ $count -eq 0 ]; then
        echo "No mobile accounts found on this device."
        return
    fi
    
    echo ""
    read -p "Enter the number of the account to delete (1-$count): " selection
    
    if [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le $count ]; then
        local selected_user="${mobile_accounts[$((selection-1))]}"
        
        echo ""
        echo "Selected account: $selected_user"
        
        # Show account details
        local real_name=$(dscl . -read "/Users/$selected_user" RealName 2>/dev/null | cut -d: -f2 | xargs)
        local home_dir=$(dscl . -read "/Users/$selected_user" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
        
        echo "Real Name: $real_name"
        echo "Home Directory: $home_dir"
        
        # Check if user is logged in
        if who | grep -q "^$selected_user "; then
            echo "Warning: User is currently logged in!"
            read -p "Do you want to continue anyway? (y/N): " force_delete
            if [ "$force_delete" != "y" ] && [ "$force_delete" != "Y" ]; then
                echo "Deletion cancelled."
                return
            fi
        fi
        
        echo ""
        read -p "Are you sure you want to delete this account? (y/N): " confirm
        
        if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
            delete_single_mobile_account "$selected_user"
        else
            echo "Deletion cancelled."
        fi
    else
        echo "Invalid selection."
    fi
}

delete_single_mobile_account() {
    local username="$1"
    
    echo "Deleting mobile account: $username"
    
    # Create backup of user data
    local backup_dir="/var/backups/macfleet/mobile_accounts"
    mkdir -p "$backup_dir"
    
    local backup_file="$backup_dir/${username}_backup_$(date +%Y%m%d_%H%M%S).txt"
    
    echo "Creating backup of user data..."
    dscl . -read "/Users/$username" > "$backup_file"
    
    # Delete user from directory services
    if dscl . -delete "/Users/$username" 2>/dev/null; then
        echo "User record deleted from directory services"
    else
        echo "Failed to delete user record from directory services"
        return 1
    fi
    
    # Remove user's home directory
    local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
    if [ -d "$home_dir" ]; then
        read -p "Do you want to remove the home directory? (y/N): " remove_home
        if [ "$remove_home" = "y" ] || [ "$remove_home" = "Y" ]; then
            if rm -rf "$home_dir"; then
                echo "Home directory removed: $home_dir"
            else
                echo "Failed to remove home directory: $home_dir"
            fi
        else
            echo "Home directory preserved: $home_dir"
        fi
    fi
    
    echo "Successfully deleted mobile account: $username"
    echo "Backup created: $backup_file"
    echo "[$timestamp] Successfully deleted mobile account: $username" >> "$log_file"
}

delete_inactive_mobile_accounts() {
    echo "======================================="
    echo "Delete Inactive Mobile Accounts"
    echo "======================================="
    
    read -p "Enter number of days since last login to consider inactive (default: 30): " days_inactive
    days_inactive=${days_inactive:-30}
    
    echo "Searching for mobile accounts inactive for more than $days_inactive days..."
    
    local inactive_accounts=()
    local current_timestamp=$(date +%s)
    local cutoff_timestamp=$((current_timestamp - (days_inactive * 24 * 60 * 60)))
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            # Check last login
            local last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $3, $4, $5, $6}')
            
            if [ -n "$last_login" ]; then
                local last_login_timestamp=$(date -j -f "%a %b %d %H:%M:%S %Y" "$last_login" +%s 2>/dev/null)
                
                if [ -n "$last_login_timestamp" ] && [ "$last_login_timestamp" -lt "$cutoff_timestamp" ]; then
                    inactive_accounts+=("$username")
                    echo "Inactive account found: $username (last login: $last_login)"
                fi
            else
                # No login record found - consider as inactive
                inactive_accounts+=("$username")
                echo "Inactive account found: $username (no login record)"
            fi
        fi
    done
    
    if [ ${#inactive_accounts[@]} -eq 0 ]; then
        echo "No inactive mobile accounts found."
        return
    fi
    
    echo ""
    echo "Found ${#inactive_accounts[@]} inactive mobile accounts."
    read -p "Do you want to delete all inactive accounts? (y/N): " confirm
    
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        for username in "${inactive_accounts[@]}"; do
            echo "Deleting inactive account: $username"
            delete_single_mobile_account "$username"
        done
        echo "Inactive mobile accounts deletion completed."
    else
        echo "Deletion cancelled."
    fi
}

delete_mobile_accounts_by_criteria() {
    echo "======================================="
    echo "Delete Mobile Accounts by Criteria"
    echo "======================================="
    
    echo "Available criteria:"
    echo "1. By UID range"
    echo "2. By home directory pattern"
    echo "3. By real name pattern"
    echo "4. By last login date"
    echo ""
    read -p "Select criteria (1-4): " criteria
    
    case $criteria in
        1)
            delete_by_uid_range
            ;;
        2)
            delete_by_home_pattern
            ;;
        3)
            delete_by_name_pattern
            ;;
        4)
            delete_by_login_date
            ;;
        *)
            echo "Invalid criteria selected."
            ;;
    esac
}

delete_by_uid_range() {
    read -p "Enter minimum UID: " min_uid
    read -p "Enter maximum UID: " max_uid
    
    echo "Searching for mobile accounts with UID between $min_uid and $max_uid..."
    
    local matching_accounts=()
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            local uid=$(dscl . -read "/Users/$username" UniqueID 2>/dev/null | cut -d: -f2 | xargs)
            
            if [ "$uid" -ge "$min_uid" ] && [ "$uid" -le "$max_uid" ]; then
                matching_accounts+=("$username")
                echo "Found matching account: $username (UID: $uid)"
            fi
        fi
    done
    
    if [ ${#matching_accounts[@]} -eq 0 ]; then
        echo "No mobile accounts found matching the UID criteria."
        return
    fi
    
    echo ""
    echo "Found ${#matching_accounts[@]} matching mobile accounts."
    read -p "Do you want to delete all matching accounts? (y/N): " confirm
    
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        for username in "${matching_accounts[@]}"; do
            delete_single_mobile_account "$username"
        done
        echo "Mobile accounts deletion by UID range completed."
    else
        echo "Deletion cancelled."
    fi
}

delete_by_home_pattern() {
    read -p "Enter home directory pattern (e.g., /Users/temp*): " pattern
    
    echo "Searching for mobile accounts with home directory matching pattern: $pattern"
    
    local matching_accounts=()
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
            
            if [[ "$home_dir" == $pattern ]]; then
                matching_accounts+=("$username")
                echo "Found matching account: $username (Home: $home_dir)"
            fi
        fi
    done
    
    if [ ${#matching_accounts[@]} -eq 0 ]; then
        echo "No mobile accounts found matching the home directory pattern."
        return
    fi
    
    echo ""
    echo "Found ${#matching_accounts[@]} matching mobile accounts."
    read -p "Do you want to delete all matching accounts? (y/N): " confirm
    
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        for username in "${matching_accounts[@]}"; do
            delete_single_mobile_account "$username"
        done
        echo "Mobile accounts deletion by home directory pattern completed."
    else
        echo "Deletion cancelled."
    fi
}

delete_by_name_pattern() {
    read -p "Enter real name pattern (e.g., *Test*): " pattern
    
    echo "Searching for mobile accounts with real name matching pattern: $pattern"
    
    local matching_accounts=()
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            local real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | cut -d: -f2 | xargs)
            
            if [[ "$real_name" == $pattern ]]; then
                matching_accounts+=("$username")
                echo "Found matching account: $username (Real Name: $real_name)"
            fi
        fi
    done
    
    if [ ${#matching_accounts[@]} -eq 0 ]; then
        echo "No mobile accounts found matching the real name pattern."
        return
    fi
    
    echo ""
    echo "Found ${#matching_accounts[@]} matching mobile accounts."
    read -p "Do you want to delete all matching accounts? (y/N): " confirm
    
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        for username in "${matching_accounts[@]}"; do
            delete_single_mobile_account "$username"
        done
        echo "Mobile accounts deletion by real name pattern completed."
    else
        echo "Deletion cancelled."
    fi
}

delete_by_login_date() {
    read -p "Enter cutoff date (YYYY-MM-DD): " cutoff_date
    
    local cutoff_timestamp=$(date -j -f "%Y-%m-%d" "$cutoff_date" +%s 2>/dev/null)
    
    if [ -z "$cutoff_timestamp" ]; then
        echo "Invalid date format. Please use YYYY-MM-DD format."
        return
    fi
    
    echo "Searching for mobile accounts with last login before $cutoff_date..."
    
    local matching_accounts=()
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            local last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $3, $4, $5, $6}')
            
            if [ -n "$last_login" ]; then
                local last_login_timestamp=$(date -j -f "%a %b %d %H:%M:%S %Y" "$last_login" +%s 2>/dev/null)
                
                if [ -n "$last_login_timestamp" ] && [ "$last_login_timestamp" -lt "$cutoff_timestamp" ]; then
                    matching_accounts+=("$username")
                    echo "Found matching account: $username (last login: $last_login)"
                fi
            else
                # No login record - consider as before cutoff
                matching_accounts+=("$username")
                echo "Found matching account: $username (no login record)"
            fi
        fi
    done
    
    if [ ${#matching_accounts[@]} -eq 0 ]; then
        echo "No mobile accounts found with last login before $cutoff_date."
        return
    fi
    
    echo ""
    echo "Found ${#matching_accounts[@]} matching mobile accounts."
    read -p "Do you want to delete all matching accounts? (y/N): " confirm
    
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        for username in "${matching_accounts[@]}"; do
            delete_single_mobile_account "$username"
        done
        echo "Mobile accounts deletion by login date completed."
    else
        echo "Deletion cancelled."
    fi
}

export_mobile_account_report() {
    echo "======================================="
    echo "Export Mobile Account Report"
    echo "======================================="
    
    local report_file="/tmp/mobile_accounts_report_$(date +%Y%m%d_%H%M%S).txt"
    
    cat > "$report_file" << EOF
MacFleet Mobile Account Report
Generated: $(date)
Device: $(scutil --get ComputerName)
macOS Version: $(sw_vers -productVersion)

Mobile Accounts Summary:
EOF
    
    local count=0
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            ((count++))
            
            echo "" >> "$report_file"
            echo "[$count] Username: $username" >> "$report_file"
            
            # Get detailed information
            local real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | cut -d: -f2 | xargs)
            local uid=$(dscl . -read "/Users/$username" UniqueID 2>/dev/null | cut -d: -f2 | xargs)
            local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
            local last_login=$(last -1 "$username" 2>/dev/null | head -1)
            
            echo "    Real Name: $real_name" >> "$report_file"
            echo "    UID: $uid" >> "$report_file"
            echo "    Home Directory: $home_dir" >> "$report_file"
            echo "    Last Login: $last_login" >> "$report_file"
            
            # Check if user is logged in
            if who | grep -q "^$username "; then
                echo "    Status: Currently logged in" >> "$report_file"
            else
                echo "    Status: Not logged in" >> "$report_file"
            fi
            
            # Check home directory size
            if [ -d "$home_dir" ]; then
                local dir_size=$(du -sh "$home_dir" 2>/dev/null | cut -f1)
                echo "    Home Directory Size: $dir_size" >> "$report_file"
            fi
        fi
    done
    
    echo "" >> "$report_file"
    echo "Total Mobile Accounts: $count" >> "$report_file"
    
    echo "Mobile account report exported to: $report_file"
}

restore_mobile_account_backup() {
    echo "======================================="
    echo "Restore Mobile Account Backup"
    echo "======================================="
    
    local backup_dir="/var/backups/macfleet/mobile_accounts"
    
    if [ ! -d "$backup_dir" ]; then
        echo "No backup directory found: $backup_dir"
        return
    fi
    
    echo "Available backups:"
    ls -la "$backup_dir"/*.txt 2>/dev/null || echo "No backup files found."
    
    echo ""
    read -p "Enter the backup filename to restore: " backup_file
    
    if [ -f "$backup_dir/$backup_file" ]; then
        echo "Backup file found: $backup_dir/$backup_file"
        echo "Note: This feature shows backup content for reference."
        echo "Manual restoration may be required for complex scenarios."
        echo ""
        cat "$backup_dir/$backup_file"
    else
        echo "Backup file not found: $backup_dir/$backup_file"
    fi
}

# Execute selective management
selective_mobile_account_manager

Enterprise Mobile Account Management

Automated Mobile Account Cleanup

#!/bin/bash

# Automated mobile account cleanup for enterprise environments
# Usage: ./automated_mobile_cleanup.sh

automated_mobile_cleanup() {
    local config_file="/etc/macfleet/mobile_cleanup_config.conf"
    local log_file="/var/log/macfleet_automated_cleanup.log"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # Check if running as root
    if [ "$EUID" -ne 0 ]; then
        echo "Error: This script must be run as root"
        exit 1
    fi
    
    # Create configuration if it doesn't exist
    if [ ! -f "$config_file" ]; then
        create_cleanup_config
    fi
    
    source "$config_file"
    
    echo "[$timestamp] Automated mobile account cleanup started" >> "$log_file"
    
    # Execute cleanup based on configuration
    execute_automated_cleanup
}

create_cleanup_config() {
    mkdir -p /etc/macfleet
    
    cat > "/etc/macfleet/mobile_cleanup_config.conf" << 'EOF'
# MacFleet Automated Mobile Account Cleanup Configuration

# Organization settings
ORGANIZATION_NAME="MacFleet Organization"
IT_CONTACT="support@macfleet.com"

# Cleanup criteria
CLEANUP_INACTIVE_DAYS="30"
CLEANUP_ENABLED="true"
PRESERVE_ADMIN_ACCOUNTS="true"

# Safety settings
REQUIRE_CONFIRMATION="true"
CREATE_BACKUP="true"
PRESERVE_HOME_DATA="false"
SKIP_LOGGED_IN_USERS="true"

# Notification settings
SEND_NOTIFICATIONS="true"
NOTIFICATION_EMAIL="admin@macfleet.com"

# Scheduling
ENABLE_SCHEDULED_CLEANUP="false"
CLEANUP_SCHEDULE="weekly"
CLEANUP_TIME="02:00"

# Logging
ENABLE_DETAILED_LOGGING="true"
LOG_RETENTION_DAYS="90"
EOF
    
    echo "Cleanup configuration created at /etc/macfleet/mobile_cleanup_config.conf"
}

execute_automated_cleanup() {
    echo "[$timestamp] Executing automated mobile account cleanup" >> "$log_file"
    
    # Check if cleanup is enabled
    if [ "$CLEANUP_ENABLED" != "true" ]; then
        echo "[$timestamp] Automated cleanup is disabled" >> "$log_file"
        echo "Automated cleanup is disabled in configuration."
        return
    fi
    
    # Display cleanup configuration
    echo "======================================="
    echo "MacFleet Automated Mobile Account Cleanup"
    echo "======================================="
    echo "Organization: $ORGANIZATION_NAME"
    echo "Cleanup inactive accounts older than: $CLEANUP_INACTIVE_DAYS days"
    echo "Preserve admin accounts: $PRESERVE_ADMIN_ACCOUNTS"
    echo "Create backup: $CREATE_BACKUP"
    echo "Skip logged in users: $SKIP_LOGGED_IN_USERS"
    echo ""
    
    # Require confirmation if enabled
    if [ "$REQUIRE_CONFIRMATION" = "true" ]; then
        read -p "Do you want to proceed with automated cleanup? (y/N): " confirm
        if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
            echo "[$timestamp] Automated cleanup cancelled by user" >> "$log_file"
            echo "Automated cleanup cancelled."
            return
        fi
    fi
    
    # Find accounts to cleanup
    local accounts_to_cleanup=()
    local current_timestamp=$(date +%s)
    local cutoff_timestamp=$((current_timestamp - (CLEANUP_INACTIVE_DAYS * 24 * 60 * 60)))
    
    echo "Scanning for mobile accounts to cleanup..."
    
    for username in $(dscl . -list /Users | grep -v '^_'); do
        auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
        
        if [ -n "$auth_authority" ]; then
            local should_cleanup=true
            
            # Check if user is admin (if preservation is enabled)
            if [ "$PRESERVE_ADMIN_ACCOUNTS" = "true" ]; then
                if dscl . -read "/Groups/admin" GroupMembership 2>/dev/null | grep -q "$username"; then
                    echo "Skipping admin account: $username"
                    echo "[$timestamp] Skipped admin account: $username" >> "$log_file"
                    should_cleanup=false
                fi
            fi
            
            # Check if user is logged in (if skip is enabled)
            if [ "$SKIP_LOGGED_IN_USERS" = "true" ] && who | grep -q "^$username "; then
                echo "Skipping logged in user: $username"
                echo "[$timestamp] Skipped logged in user: $username" >> "$log_file"
                should_cleanup=false
            fi
            
            # Check last login date
            if [ "$should_cleanup" = true ]; then
                local last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $3, $4, $5, $6}')
                
                if [ -n "$last_login" ]; then
                    local last_login_timestamp=$(date -j -f "%a %b %d %H:%M:%S %Y" "$last_login" +%s 2>/dev/null)
                    
                    if [ -n "$last_login_timestamp" ] && [ "$last_login_timestamp" -lt "$cutoff_timestamp" ]; then
                        accounts_to_cleanup+=("$username")
                        echo "Account marked for cleanup: $username (last login: $last_login)"
                    fi
                else
                    # No login record - consider for cleanup
                    accounts_to_cleanup+=("$username")
                    echo "Account marked for cleanup: $username (no login record)"
                fi
            fi
        fi
    done
    
    if [ ${#accounts_to_cleanup[@]} -eq 0 ]; then
        echo "No mobile accounts found that meet cleanup criteria."
        echo "[$timestamp] No mobile accounts found for cleanup" >> "$log_file"
        return
    fi
    
    echo ""
    echo "Found ${#accounts_to_cleanup[@]} mobile accounts for cleanup:"
    for account in "${accounts_to_cleanup[@]}"; do
        echo "  - $account"
    done
    
    # Create backup if enabled
    if [ "$CREATE_BACKUP" = "true" ]; then
        create_automated_backup "${accounts_to_cleanup[@]}"
    fi
    
    # Cleanup accounts
    local success_count=0
    local failure_count=0
    
    echo ""
    echo "Starting automated cleanup..."
    
    for username in "${accounts_to_cleanup[@]}"; do
        echo "Processing: $username"
        
        # Delete user from directory services
        if dscl . -delete "/Users/$username" 2>/dev/null; then
            echo "  Deleted user record from directory services"
            
            # Handle home directory based on configuration
            local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
            
            if [ -d "$home_dir" ]; then
                if [ "$PRESERVE_HOME_DATA" = "true" ]; then
                    echo "  Preserved home directory: $home_dir"
                else
                    if rm -rf "$home_dir" 2>/dev/null; then
                        echo "  Removed home directory: $home_dir"
                    else
                        echo "  Warning: Failed to remove home directory: $home_dir"
                    fi
                fi
            fi
            
            echo "  Successfully cleaned up account: $username"
            echo "[$timestamp] Successfully cleaned up account: $username" >> "$log_file"
            ((success_count++))
        else
            echo "  Failed to cleanup account: $username"
            echo "[$timestamp] Failed to cleanup account: $username" >> "$log_file"
            ((failure_count++))
        fi
    done
    
    # Generate cleanup summary
    echo ""
    echo "======================================="
    echo "Automated Cleanup Summary"
    echo "======================================="
    echo "Total accounts processed: ${#accounts_to_cleanup[@]}"
    echo "Successfully cleaned up: $success_count"
    echo "Failed to cleanup: $failure_count"
    echo "Cleanup completed at: $(date)"
    
    echo "[$timestamp] Automated cleanup completed - Success: $success_count, Failed: $failure_count" >> "$log_file"
    
    # Send notification if enabled
    if [ "$SEND_NOTIFICATIONS" = "true" ]; then
        send_cleanup_notification "$success_count" "$failure_count"
    fi
    
    echo ""
    echo "Note: Please restart the device for changes to take full effect."
}

create_automated_backup() {
    local accounts=("$@")
    local backup_dir="/var/backups/macfleet/automated_cleanup"
    local backup_file="$backup_dir/cleanup_backup_$(date +%Y%m%d_%H%M%S).txt"
    
    mkdir -p "$backup_dir"
    
    echo "Creating backup of accounts to be cleaned up..."
    
    cat > "$backup_file" << EOF
MacFleet Automated Cleanup Backup
Generated: $(date)
Device: $(scutil --get ComputerName)
Organization: $ORGANIZATION_NAME
Cleanup Criteria: Inactive for $CLEANUP_INACTIVE_DAYS days

Accounts to be cleaned up:
EOF
    
    for username in "${accounts[@]}"; do
        echo "" >> "$backup_file"
        echo "Username: $username" >> "$backup_file"
        dscl . -read "/Users/$username" >> "$backup_file" 2>/dev/null
        echo "---" >> "$backup_file"
    done
    
    echo "Backup created: $backup_file"
    echo "[$timestamp] Automated cleanup backup created: $backup_file" >> "$log_file"
}

send_cleanup_notification() {
    local success_count=$1
    local failure_count=$2
    
    local notification_subject="MacFleet Mobile Account Cleanup Report"
    local notification_body="Automated mobile account cleanup completed.

Device: $(scutil --get ComputerName)
Organization: $ORGANIZATION_NAME
Cleanup Date: $(date)

Results:
- Successfully cleaned up: $success_count accounts
- Failed to cleanup: $failure_count accounts
- Total processed: $((success_count + failure_count)) accounts

For detailed logs, check: /var/log/macfleet_automated_cleanup.log

Contact: $IT_CONTACT"
    
    # Use osascript to display notification (for local notifications)
    osascript -e "display notification \"Cleanup completed: $success_count success, $failure_count failed\" with title \"MacFleet Mobile Account Cleanup\""
    
    echo "[$timestamp] Cleanup notification sent" >> "$log_file"
}

# Execute automated cleanup
automated_mobile_cleanup

Troubleshooting and Best Practices

Common Issues and Solutions

  1. Permission Errors: Always run scripts as root using sudo
  2. Logged-in Users: Check for active sessions before deletion
  3. Directory Services: Verify mobile account identification using LocalCachedUser attribute
  4. Home Directory Protection: Create backups before removing home directories
  5. Network Accounts: Ensure network connectivity for directory service operations

Best Practices

  • Test First: Always test scripts in controlled environments
  • Create Backups: Maintain backups of user data before deletion
  • Log Operations: Keep detailed logs of all account operations
  • User Communication: Notify users before account cleanup
  • Schedule Maintenance: Perform cleanup during maintenance windows

Conclusion

Mobile account management is crucial for maintaining clean and secure macOS environments. These scripts provide comprehensive solutions for deleting mobile accounts, from simple cleanup to enterprise-grade automation. Always ensure proper testing and backup procedures before implementing in production environments.

Delete Files by Size on macOS

Learn how to find and delete large files on Mac devices based on size criteria. This helps free up storage space and improve device performance when storage is running low.

List Large Files

Find and list files larger than a specified size:

#!/bin/bash

# Get current user context
CURRENT_USER=$(stat -f "%Su" /dev/console)
CURRENT_USER_UID=$(id -u "$CURRENT_USER")

# Configuration
SEARCH_PATH="/Users/$CURRENT_USER/Desktop"
SIZE_LIMIT="100"  # Size in kilobytes

echo "Searching for files larger than ${SIZE_LIMIT}KB in: $SEARCH_PATH"

# List large files
launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" \
    find "$SEARCH_PATH" -type f -size +${SIZE_LIMIT}k -print

Delete Large Files

Find and delete files larger than specified size:

#!/bin/bash

# Get current user context
CURRENT_USER=$(stat -f "%Su" /dev/console)
CURRENT_USER_UID=$(id -u "$CURRENT_USER")

# Configuration
SEARCH_PATH="/Users/$CURRENT_USER/Downloads"
SIZE_LIMIT="50"  # Size in kilobytes

echo "⚠️  WARNING: This will permanently delete files larger than ${SIZE_LIMIT}KB"
echo "Searching in: $SEARCH_PATH"

# List and delete large files
launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" \
    find "$SEARCH_PATH" -type f -size +${SIZE_LIMIT}k -print -delete

echo "✅ Large files deleted successfully"

Enhanced File Cleanup Script

Script with safety checks and detailed reporting:

#!/bin/bash

# Function to cleanup large files safely
cleanup_large_files() {
    local search_path="$1"
    local size_limit="$2"
    local dry_run="${3:-false}"
    
    # Get current user context
    local current_user=$(stat -f "%Su" /dev/console)
    local current_user_uid=$(id -u "$current_user")
    
    if [[ ! -d "$search_path" ]]; then
        echo "❌ Error: Directory not found: $search_path"
        return 1
    fi
    
    echo "=== Large Files Cleanup ==="
    echo "📁 Path: $search_path"
    echo "📏 Size limit: ${size_limit}KB"
    echo "👤 User: $current_user"
    echo "🔍 Dry run: $dry_run"
    echo "=========================="
    
    # Find large files
    local files_command="find '$search_path' -type f -size +${size_limit}k"
    
    if [[ "$dry_run" == "true" ]]; then
        echo "📋 Files that would be deleted:"
        launchctl asuser $current_user_uid sudo -iu "$current_user" \
            bash -c "$files_command -ls"
        
        local count=$(launchctl asuser $current_user_uid sudo -iu "$current_user" \
            bash -c "$files_command | wc -l")
        echo "📊 Total files found: $count"
    else
        echo "🗑️  Deleting large files..."
        launchctl asuser $current_user_uid sudo -iu "$current_user" \
            bash -c "$files_command -print -delete"
        echo "✅ Cleanup completed"
    fi
}

# Configuration
SEARCH_PATH="/Users/$(stat -f "%Su" /dev/console)/Downloads"
SIZE_LIMIT="100"
DRY_RUN="true"  # Set to "false" to actually delete files

# Run cleanup
cleanup_large_files "$SEARCH_PATH" "$SIZE_LIMIT" "$DRY_RUN"

Enterprise Storage Management

Comprehensive storage cleanup for enterprise environments:

#!/bin/bash

# Enterprise storage cleanup configuration
CLEANUP_LOCATIONS=(
    "/Users/*/Downloads:50"
    "/Users/*/Desktop:100"
    "/Users/*/Documents:200"
    "/tmp:10"
)

# Function to format file size
format_size() {
    local size=$1
    if [[ $size -gt 1048576 ]]; then
        echo "$(( size / 1048576 ))GB"
    elif [[ $size -gt 1024 ]]; then
        echo "$(( size / 1024 ))MB"
    else
        echo "${size}KB"
    fi
}

# Function to get directory size
get_directory_size() {
    local dir="$1"
    if [[ -d "$dir" ]]; then
        du -sk "$dir" 2>/dev/null | cut -f1
    else
        echo "0"
    fi
}

# Enterprise cleanup execution
echo "🏢 MacFleet Enterprise Storage Cleanup"
echo "======================================"
echo "Generated: $(date)"
echo "Device: $(hostname)"

total_freed=0
current_user=$(stat -f "%Su" /dev/console)
current_user_uid=$(id -u "$current_user")

for location_config in "${CLEANUP_LOCATIONS[@]}"; do
    IFS=':' read -r location_pattern size_limit <<< "$location_config"
    
    echo ""
    echo "📁 Processing: $location_pattern (>${size_limit}KB)"
    
    # Expand pattern for user directories
    for location in $location_pattern; do
        if [[ -d "$location" ]]; then
            echo "  🔍 Scanning: $location"
            
            # Get before size
            before_size=$(get_directory_size "$location")
            
            # Find and delete large files
            deleted_files=$(launchctl asuser $current_user_uid sudo -iu "$current_user" \
                find "$location" -type f -size +${size_limit}k -print -delete 2>/dev/null | wc -l)
            
            # Get after size
            after_size=$(get_directory_size "$location")
            freed=$((before_size - after_size))
            total_freed=$((total_freed + freed))
            
            if [[ $deleted_files -gt 0 ]]; then
                echo "  ✅ Deleted: $deleted_files files"
                echo "  💾 Freed: $(format_size $freed)"
            else
                echo "  ℹ️  No large files found"
            fi
        fi
    done
done

echo ""
echo "======================================"
echo "📊 Summary:"
echo "  Total space freed: $(format_size $total_freed)"
echo "  Cleanup completed: $(date)"

if [[ $total_freed -gt 0 ]]; then
    echo "✅ Storage cleanup successful"
else
    echo "ℹ️  No cleanup needed - storage usage is optimal"
fi

Safe Cleanup with Backup Option

Script with optional backup before deletion:

#!/bin/bash

# Function to backup large files before deletion
backup_and_delete() {
    local search_path="$1"
    local size_limit="$2"
    local backup_enabled="${3:-false}"
    
    local current_user=$(stat -f "%Su" /dev/console)
    local current_user_uid=$(id -u "$current_user")
    local backup_dir="/tmp/macfleet_backup_$(date +%Y%m%d_%H%M%S)"
    
    echo "🔄 Processing: $search_path"
    
    if [[ "$backup_enabled" == "true" ]]; then
        echo "📦 Creating backup directory: $backup_dir"
        mkdir -p "$backup_dir"
        
        # Find and backup large files
        launchctl asuser $current_user_uid sudo -iu "$current_user" \
            find "$search_path" -type f -size +${size_limit}k -exec cp {} "$backup_dir/" \;
        
        echo "✅ Files backed up to: $backup_dir"
    fi
    
    # Delete large files
    local deleted_count=$(launchctl asuser $current_user_uid sudo -iu "$current_user" \
        find "$search_path" -type f -size +${size_limit}k -print -delete | wc -l)
    
    echo "🗑️  Deleted $deleted_count large files"
    
    if [[ "$backup_enabled" == "true" && $deleted_count -gt 0 ]]; then
        echo "💡 Backup location: $backup_dir"
        echo "⏰ Backup will be auto-removed in 7 days"
        
        # Schedule backup cleanup (requires launchd or cron)
        echo "find '$backup_dir' -type f -mtime +7 -delete" > /tmp/cleanup_backup.sh
        chmod +x /tmp/cleanup_backup.sh
    fi
}

# Configuration
SEARCH_PATH="/Users/$(stat -f "%Su" /dev/console)/Downloads"
SIZE_LIMIT="100"
BACKUP_ENABLED="true"

# Execute safe cleanup
backup_and_delete "$SEARCH_PATH" "$SIZE_LIMIT" "$BACKUP_ENABLED"

Usage with MacFleet

  1. Configure search path and size limit in the script
  2. Choose between dry-run and actual deletion modes
  3. Consider enabling backup option for safety
  4. Deploy through MacFleet's remote script execution
  5. Monitor results and freed space in action history

Size Units and Examples

UnitDescriptionExample Use Case
+50kFiles larger than 50KBSmall document cleanup
+10MFiles larger than 10MBMedia file cleanup
+100MFiles larger than 100MBLarge file cleanup
+1GFiles larger than 1GBArchive cleanup

Common Cleanup Targets

DirectoryTypical Size LimitPurpose
Downloads50MBRemove large downloads
Desktop100MBClean desktop files
Documents200MBArchive old documents
Temp folders10MBSystem cleanup

Safety Considerations

⚠️ CRITICAL WARNING: Files deleted with these scripts are permanently removed and cannot be recovered from Trash.

  • Test first: Always run with dry-run mode enabled initially
  • Backup important data: Consider backup option for valuable files
  • Verify paths: Double-check search directories before execution
  • User context: Scripts run in current user context for security

Troubleshooting

Permission denied: Ensure proper user context with launchctl asuser Directory not found: Verify search paths exist before running No files found: Check size limits and directory contents


Note: Always validate scripts on test systems before bulk deployment. Permanent file deletion requires careful consideration and backup planning.

Date and Time Management on macOS

Manage date and time settings across your MacFleet with enterprise-grade automation, validation controls, and comprehensive monitoring capabilities.

Understanding Enterprise Date and Time Management

Enterprise date and time management requires more than basic date setting, demanding:

  • Automated validation and formatting with enterprise-grade error handling
  • Scheduled date/time operations with business logic integration
  • Compliance tracking for audit requirements and regulatory standards
  • Real-time monitoring of date/time changes and system integrity
  • Integration capabilities with enterprise scheduling and workflow systems
  • Security controls to prevent unauthorized time manipulation

Core Date and Time Management Process

Basic Commands

  1. Set Date/Time - date MMDDhhmm[[CC]YY][.ss]
  2. Parameterized Setting - date $1 (with argument passing)

Core Date Format

The format follows: MMDDhhmm[[CC]YY][.ss]

  • MM - Month (01-12)
  • DD - Day (01-31)
  • hh - Hour (00-23)
  • mm - Minutes (00-59)
  • CC - Century (optional)
  • YY - Year (optional)
  • ss - Seconds (optional)

Basic Configuration Examples

# Basic date setting
date 120614302023.00  # December 6, 2023 2:30 PM

# Parameterized version
date $1  # Pass date as argument

Enterprise Date and Time Management System

#!/bin/bash

# MacFleet Enterprise Date and Time Management System
# Comprehensive date/time management with enterprise controls and monitoring

# Configuration
SCRIPT_NAME="MacFleet Date/Time Manager"
VERSION="1.0.0"
LOG_FILE="/var/log/macfleet_datetime.log"
AUDIT_LOG="/var/log/macfleet_datetime_audit.log"
CONFIG_DIR="/etc/macfleet/datetime"
POLICIES_DIR="/etc/macfleet/datetime/policies"
BACKUP_DIR="/var/backups/datetime"
TEMP_DIR="/tmp/macfleet_datetime"
ORGANIZATION_NAME="MacFleet Enterprise"
DEPLOYMENT_MODE="enterprise"
ENABLE_VALIDATION=true
ENABLE_AUDIT_LOGGING=true
ENABLE_BACKUP_RESTORE=true
MAX_TIME_DRIFT_HOURS=24
BUSINESS_HOURS_START="08:00"
BUSINESS_HOURS_END="18:00"

# Date/Time Validation Patterns
declare -A DATE_FORMATS=(
    ["macfleet"]="MMDDhhmm[[CC]YY][.ss]"
    ["iso8601"]="YYYY-MM-DDTHH:MM:SS"
    ["unix"]="seconds_since_epoch"
    ["readable"]="Month DD, YYYY HH:MM:SS"
)

# Enterprise Scheduling Policies
declare -A SCHEDULING_POLICIES=(
    ["immediate"]="execute_now"
    ["business_hours"]="within_business_hours_only"
    ["maintenance_window"]="scheduled_maintenance_only"
    ["emergency"]="override_all_restrictions"
)

# Compliance Standards
declare -A COMPLIANCE_REQUIREMENTS=(
    ["SOX"]="financial_audit_trail"
    ["HIPAA"]="healthcare_time_integrity"
    ["PCI_DSS"]="payment_transaction_accuracy"
    ["ISO27001"]="information_security_timestamps"
)

# Create necessary directories
mkdir -p "$CONFIG_DIR"
mkdir -p "$POLICIES_DIR"
mkdir -p "$BACKUP_DIR"
mkdir -p "$TEMP_DIR"
mkdir -p "$(dirname "$LOG_FILE")"
mkdir -p "$(dirname "$AUDIT_LOG")"

# Set secure permissions
chmod 755 "$CONFIG_DIR"
chmod 750 "$POLICIES_DIR"
chmod 750 "$BACKUP_DIR"
chmod 700 "$TEMP_DIR"

# Logging functions
log_operation() {
    local level="$1"
    local message="$2"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local admin_user=$(whoami)
    echo "[$timestamp] [$level] [$admin_user] $message" | tee -a "$LOG_FILE"
}

log_security_event() {
    local event_type="$1"
    local details="$2"
    local severity="$3"
    local admin_user=$(whoami)
    
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local source_ip=$(who am i | awk '{print $5}' | tr -d '()')
    echo "SECURITY|$timestamp|$event_type|$severity|$admin_user|$source_ip|$details" >> "$AUDIT_LOG"
}

# Get current date and time information
get_current_datetime() {
    local format="${1:-all}"
    
    echo "=== Current Date and Time Information ==="
    echo "Local Time: $(date '+%Y-%m-%d %H:%M:%S %Z')"
    echo "UTC Time: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
    echo "Unix Timestamp: $(date +%s)"
    echo "Uptime: $(uptime | awk -F'up ' '{print $2}' | awk -F',' '{print $1}')"
    
    case "$format" in
        "macfleet")
            echo "Macfleet Format: $(date '+%m%d%H%M%Y.%S')"
            ;;
        "iso8601")
            echo "ISO 8601 Format: $(date '+%Y-%m-%dT%H:%M:%S')"
            ;;
        "detailed")
            echo ""
            echo "Detailed Information:"
            echo "  Year: $(date '+%Y')"
            echo "  Month: $(date '+%m') ($(date '+%B'))"
            echo "  Day: $(date '+%d')"
            echo "  Hour: $(date '+%H')"
            echo "  Minute: $(date '+%M')"
            echo "  Second: $(date '+%S')"
            echo "  Day of Week: $(date '+%A')"
            echo "  Day of Year: $(date '+%j')"
            echo "  Week of Year: $(date '+%U')"
            ;;
    esac
    echo ""
}

# Validate date/time format
validate_datetime_format() {
    local datetime_string="$1"
    local format_type="${2:-macfleet}"
    
    echo "=== Date/Time Format Validation ==="
    echo "Input: $datetime_string"
    echo "Expected Format: $format_type"
    echo ""
    
    case "$format_type" in
        "macfleet")
            # Validate Macfleet format: MMDDhhmm[[CC]YY][.ss]
            if [[ "$datetime_string" =~ ^[0-9]{8}([0-9]{4})?(\.[0-9]{2})?$ ]]; then
                local month="${datetime_string:0:2}"
                local day="${datetime_string:2:2}"
                local hour="${datetime_string:4:2}"
                local minute="${datetime_string:6:2}"
                
                # Validate ranges
                if [[ $month -ge 1 && $month -le 12 ]] && \
                   [[ $day -ge 1 && $day -le 31 ]] && \
                   [[ $hour -ge 0 && $hour -le 23 ]] && \
                   [[ $minute -ge 0 && $minute -le 59 ]]; then
                    echo "✅ Valid Macfleet format"
                    return 0
                else
                    echo "❌ Invalid date/time values in Macfleet format"
                    return 1
                fi
            else
                echo "❌ Invalid Macfleet format structure"
                echo "Expected: MMDDhhmm[[CC]YY][.ss]"
                return 1
            fi
            ;;
        "iso8601")
            # Validate ISO 8601 format
            if date -j -f "%Y-%m-%dT%H:%M:%S" "$datetime_string" &>/dev/null; then
                echo "✅ Valid ISO 8601 format"
                return 0
            else
                echo "❌ Invalid ISO 8601 format"
                return 1
            fi
            ;;
        "unix")
            # Validate Unix timestamp
            if [[ "$datetime_string" =~ ^[0-9]+$ ]] && [[ $datetime_string -gt 0 ]]; then
                echo "✅ Valid Unix timestamp"
                return 0
            else
                echo "❌ Invalid Unix timestamp"
                return 1
            fi
            ;;
        *)
            echo "❌ Unknown format type: $format_type"
            return 1
            ;;
    esac
}

# Convert between date formats
convert_datetime_format() {
    local input_datetime="$1"
    local from_format="$2"
    local to_format="$3"
    
    echo "=== Date/Time Format Conversion ==="
    echo "Input: $input_datetime"
    echo "From: $from_format"
    echo "To: $to_format"
    echo ""
    
    local converted_datetime
    
    case "$from_format" in
        "macfleet")
            # Convert from Macfleet format
            local month="${input_datetime:0:2}"
            local day="${input_datetime:2:2}"
            local hour="${input_datetime:4:2}"
            local minute="${input_datetime:6:2}"
            local year_part="${input_datetime:8:4}"
            local seconds_part="${input_datetime:13:2}"
            
            # Default year if not provided
            if [[ -z "$year_part" ]]; then
                year_part=$(date '+%Y')
            fi
            
            # Default seconds if not provided
            if [[ -z "$seconds_part" ]]; then
                seconds_part="00"
            fi
            
            case "$to_format" in
                "iso8601")
                    converted_datetime="${year_part}-${month}-${day}T${hour}:${minute}:${seconds_part}"
                    ;;
                "readable")
                    converted_datetime=$(date -j "${month}${day}${hour}${minute}${year_part}.${seconds_part}" '+%B %d, %Y %H:%M:%S' 2>/dev/null)
                    ;;
                "unix")
                    converted_datetime=$(date -j "${month}${day}${hour}${minute}${year_part}.${seconds_part}" '+%s' 2>/dev/null)
                    ;;
            esac
            ;;
        "iso8601")
            # Convert from ISO 8601 format
            case "$to_format" in
                "macfleet")
                    converted_datetime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$input_datetime" '+%m%d%H%M%Y.%S' 2>/dev/null)
                    ;;
                "readable")
                    converted_datetime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$input_datetime" '+%B %d, %Y %H:%M:%S' 2>/dev/null)
                    ;;
                "unix")
                    converted_datetime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$input_datetime" '+%s' 2>/dev/null)
                    ;;
            esac
            ;;
        "unix")
            # Convert from Unix timestamp
            case "$to_format" in
                "macfleet")
                    converted_datetime=$(date -r "$input_datetime" '+%m%d%H%M%Y.%S' 2>/dev/null)
                    ;;
                "iso8601")
                    converted_datetime=$(date -r "$input_datetime" '+%Y-%m-%dT%H:%M:%S' 2>/dev/null)
                    ;;
                "readable")
                    converted_datetime=$(date -r "$input_datetime" '+%B %d, %Y %H:%M:%S' 2>/dev/null)
                    ;;
            esac
            ;;
    esac
    
    if [[ -n "$converted_datetime" ]]; then
        echo "✅ Conversion successful"
        echo "Result: $converted_datetime"
        echo "$converted_datetime"
        return 0
    else
        echo "❌ Conversion failed"
        return 1
    fi
}

# Set date and time with enterprise validation
set_enterprise_datetime() {
    local datetime_input="$1"
    local format_type="${2:-macfleet}"
    local policy="${3:-business_hours}"
    local force="${4:-false}"
    local admin_user=$(whoami)
    
    log_security_event "DATETIME_CHANGE_ATTEMPT" "datetime=$datetime_input,format=$format_type,policy=$policy" "INFO"
    
    echo "=== Enterprise Date/Time Configuration ==="
    echo "Input: $datetime_input"
    echo "Format: $format_type"
    echo "Policy: $policy"
    echo "Administrator: $admin_user"
    echo "Force Mode: $force"
    echo ""
    
    # Validate input format
    if ! validate_datetime_format "$datetime_input" "$format_type"; then
        log_operation "ERROR" "Invalid date/time format: $datetime_input ($format_type)"
        return 1
    fi
    
    # Check scheduling policy
    if [[ "$policy" == "business_hours" && "$force" != "true" ]]; then
        local current_hour=$(date '+%H')
        local business_start_hour="${BUSINESS_HOURS_START:0:2}"
        local business_end_hour="${BUSINESS_HOURS_END:0:2}"
        
        if [[ $current_hour -lt $business_start_hour || $current_hour -gt $business_end_hour ]]; then
            echo "⚠️  Operation requested outside business hours ($BUSINESS_HOURS_START-$BUSINESS_HOURS_END)"
            echo "Use force=true to override or wait for business hours"
            log_operation "WARNING" "Date/time change blocked by business hours policy"
            return 1
        fi
    fi
    
    # Backup current date/time
    local backup_file="$BACKUP_DIR/datetime_$(date +%Y%m%d_%H%M%S).backup"
    {
        echo "# MacFleet Date/Time Backup"
        echo "PREVIOUS_DATETIME=$(date '+%Y-%m-%d %H:%M:%S %Z')"
        echo "PREVIOUS_UTC=$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
        echo "PREVIOUS_UNIX=$(date +%s)"
        echo "BACKUP_TIMESTAMP=$(date)"
        echo "CHANGED_BY=$admin_user"
        echo "NEW_DATETIME=$datetime_input"
        echo "FORMAT_TYPE=$format_type"
        echo "POLICY=$policy"
    } > "$backup_file"
    
    log_operation "INFO" "Date/time backup created: $backup_file"
    
    # Convert to appropriate format if needed
    local macfleet_format="$datetime_input"
    
    if [[ "$format_type" != "macfleet" ]]; then
        echo "Converting $format_type to Macfleet format..."
        macfleet_format=$(convert_datetime_format "$datetime_input" "$format_type" "macfleet")
        
        if [[ $? -ne 0 ]]; then
            log_operation "ERROR" "Failed to convert date/time format"
            return 1
        fi
        
        echo "Converted format: $macfleet_format"
    fi
    
    # Validate time drift
    local current_unix=$(date +%s)
    local target_unix=$(convert_datetime_format "$macfleet_format" "macfleet" "unix")
    local time_diff=$((target_unix - current_unix))
    local time_diff_hours=$((time_diff / 3600))
    local time_diff_abs=${time_diff_hours#-}
    
    if [[ $time_diff_abs -gt $MAX_TIME_DRIFT_HOURS && "$force" != "true" ]]; then
        echo "⚠️  Large time change detected: ${time_diff_hours} hours"
        echo "This exceeds the maximum drift threshold of $MAX_TIME_DRIFT_HOURS hours"
        echo "Use force=true to override this safety check"
        log_operation "WARNING" "Large time drift blocked: ${time_diff_hours} hours"
        return 1
    fi
    
    # Apply date/time change
    echo "Setting date/time to: $macfleet_format"
    
    if sudo date "$macfleet_format" &>/dev/null; then
        echo "✅ Date/time set successfully"
        log_operation "INFO" "Date/time changed to: $macfleet_format (format: $format_type)"
        log_security_event "DATETIME_CHANGED" "new_datetime=$macfleet_format,drift_hours=$time_diff_hours,policy=$policy" "INFO"
        
        # Verify the change
        sleep 1
        echo ""
        echo "Verification:"
        get_current_datetime
        
        return 0
    else
        echo "❌ Failed to set date/time"
        log_operation "ERROR" "Failed to set date/time: $macfleet_format"
        log_security_event "DATETIME_CHANGE_FAILED" "datetime=$macfleet_format,error=date_command_failed" "ERROR"
        return 1
    fi
}

# Schedule date/time operations
schedule_datetime_operation() {
    local operation="$1"
    local target_datetime="$2"
    local schedule_time="$3"
    local policy="${4:-business_hours}"
    
    echo "=== Scheduled Date/Time Operation ==="
    echo "Operation: $operation"
    echo "Target DateTime: $target_datetime"
    echo "Schedule Time: $schedule_time"
    echo "Policy: $policy"
    echo ""
    
    # Create scheduled operation file
    local schedule_file="$POLICIES_DIR/scheduled_$(date +%Y%m%d_%H%M%S).sh"
    
    cat > "$schedule_file" << EOF
#!/bin/bash
# MacFleet Scheduled Date/Time Operation
# Generated: $(date)
# Operation: $operation
# Target: $target_datetime
# Policy: $policy

# Execute the scheduled operation
case "$operation" in
    "set_datetime")
        $0 set "$target_datetime" macfleet "$policy" true
        ;;
    "sync_time")
        sudo systemsetup -setusingnetworktime on
        ;;
    "backup_datetime")
        $0 backup
        ;;
    *)
        echo "Unknown operation: $operation"
        exit 1
        ;;
esac
EOF
    
    chmod +x "$schedule_file"
    
    # Schedule using at command (if available)
    if command -v at &>/dev/null; then
        echo "$schedule_file" | at "$schedule_time" 2>/dev/null
        
        if [[ $? -eq 0 ]]; then
            echo "✅ Operation scheduled successfully for $schedule_time"
            log_operation "INFO" "Scheduled operation: $operation at $schedule_time"
            return 0
        else
            echo "❌ Failed to schedule operation"
            log_operation "ERROR" "Failed to schedule operation: $operation"
            return 1
        fi
    else
        echo "⚠️  'at' command not available for scheduling"
        echo "Schedule file created: $schedule_file"
        echo "Execute manually or integrate with your scheduling system"
        return 1
    fi
}

# Monitor date/time integrity
monitor_datetime_integrity() {
    local check_type="${1:-basic}"
    local admin_user=$(whoami)
    
    echo "=== Date/Time Integrity Monitoring ==="
    echo "Check Type: $check_type"
    echo "Monitor: $admin_user"
    echo ""
    
    local integrity_status="HEALTHY"
    local issues=()
    
    # Check system clock vs network time
    if command -v ntpdate &>/dev/null; then
        echo "Checking time synchronization..."
        
        local ntp_time=$(ntpdate -q pool.ntp.org 2>/dev/null | tail -1 | grep -o "offset [+-][0-9.]*" | awk '{print $2}')
        
        if [[ -n "$ntp_time" ]]; then
            local offset_abs=${ntp_time#-}
            
            echo "NTP offset: ${ntp_time}s"
            
            if (( $(echo "$offset_abs > 30" | bc -l) )); then
                integrity_status="WARNING"
                issues+=("Large NTP offset: ${ntp_time}s")
            else
                echo "✅ Time synchronization within acceptable range"
            fi
        else
            integrity_status="WARNING"
            issues+=("Unable to check NTP synchronization")
        fi
    fi
    
    # Check for recent large time changes
    if [[ -f "$AUDIT_LOG" ]]; then
        echo ""
        echo "Checking recent time changes..."
        
        local recent_changes=$(grep "DATETIME_CHANGED" "$AUDIT_LOG" | tail -5)
        
        if [[ -n "$recent_changes" ]]; then
            echo "Recent date/time changes found:"
            echo "$recent_changes" | while read -r line; do
                echo "  $(echo "$line" | cut -d'|' -f2,6)"
            done
        else
            echo "✅ No recent date/time changes detected"
        fi
    fi
    
    # Advanced checks
    if [[ "$check_type" == "comprehensive" ]]; then
        echo ""
        echo "Running comprehensive integrity checks..."
        
        # Check system logs for time-related errors
        local time_errors=$(log show --predicate 'subsystem == "com.apple.time"' --last 1h 2>/dev/null | grep -i error | wc -l)
        
        if [[ $time_errors -gt 0 ]]; then
            integrity_status="WARNING"
            issues+=("System time errors detected: $time_errors")
        fi
        
        # Check for timezone mismatches
        local system_tz=$(systemsetup -gettimezone 2>/dev/null | awk -F': ' '{print $2}')
        local env_tz="$TZ"
        
        if [[ -n "$env_tz" && "$env_tz" != "$system_tz" ]]; then
            integrity_status="WARNING"
            issues+=("Timezone mismatch: system=$system_tz, env=$env_tz")
        fi
    fi
    
    # Generate integrity report
    echo ""
    echo "=== Date/Time Integrity Report ==="
    echo "Overall Status: $integrity_status"
    echo "Timestamp: $(date)"
    
    if [[ ${#issues[@]} -gt 0 ]]; then
        echo "Issues Found:"
        printf '  - %s\n' "${issues[@]}"
    else
        echo "✅ All date/time systems operating normally"
    fi
    
    # Log monitoring results
    log_operation "INFO" "Date/time integrity check completed: $integrity_status (${#issues[@]} issues)"
    log_security_event "DATETIME_INTEGRITY_CHECK" "status=$integrity_status,issues=${#issues[@]}" "INFO"
    
    # Return appropriate exit code
    case "$integrity_status" in
        "HEALTHY") return 0 ;;
        "WARNING") return 1 ;;
        "CRITICAL") return 2 ;;
        *) return 3 ;;
    esac
}

# Generate date/time management report
generate_datetime_report() {
    local report_type="${1:-summary}"
    local admin_user=$(whoami)
    local report_file="/var/reports/datetime_report_$(date +%Y%m%d_%H%M%S).txt"
    
    mkdir -p "$(dirname "$report_file")"
    
    log_security_event "REPORT_GENERATION" "type=$report_type" "INFO"
    
    {
        echo "MacFleet Date/Time Management Report"
        echo "==================================="
        echo "Report Type: $report_type"
        echo "Generated: $(date)"
        echo "Generated By: $admin_user"
        echo "Hostname: $(hostname)"
        echo ""
        
        case "$report_type" in
            "summary")
                echo "== Date/Time Summary =="
                get_current_datetime "detailed"
                
                echo "Available Formats:"
                for format in "${!DATE_FORMATS[@]}"; do
                    echo "  $format: ${DATE_FORMATS[$format]}"
                done
                ;;
            "compliance")
                echo "== Compliance Assessment =="
                
                echo "Compliance Standards:"
                for standard in "${!COMPLIANCE_REQUIREMENTS[@]}"; do
                    echo "  $standard: ${COMPLIANCE_REQUIREMENTS[$standard]}"
                done
                
                echo ""
                echo "Recent Audit Events:"
                if [[ -f "$AUDIT_LOG" ]]; then
                    tail -10 "$AUDIT_LOG"
                else
                    echo "No audit log available"
                fi
                ;;
            "audit")
                echo "== Audit Information =="
                if [[ -f "$AUDIT_LOG" ]]; then
                    echo "Complete audit trail:"
                    cat "$AUDIT_LOG"
                else
                    echo "No audit log available"
                fi
                ;;
        esac
        
        echo ""
        echo "== System Information =="
        echo "Uptime: $(uptime)"
        echo "Load Average: $(uptime | awk -F'load average:' '{print $2}')"
        
    } > "$report_file"
    
    echo "Date/time report generated: $report_file"
    log_operation "INFO" "Date/time report generated: $report_file"
}

# Backup and restore date/time settings
backup_datetime_settings() {
    local backup_type="${1:-full}"
    
    echo "=== Date/Time Settings Backup ==="
    echo "Backup Type: $backup_type"
    echo ""
    
    local backup_file="$BACKUP_DIR/datetime_settings_$(date +%Y%m%d_%H%M%S).backup"
    
    {
        echo "# MacFleet Date/Time Settings Backup"
        echo "BACKUP_DATE=$(date)"
        echo "BACKUP_TYPE=$backup_type"
        echo ""
        echo "# Current Settings"
        echo "CURRENT_DATETIME=$(date '+%Y-%m-%d %H:%M:%S %Z')"
        echo "CURRENT_UTC=$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
        echo "CURRENT_UNIX=$(date +%s)"
        echo "CURRENT_TIMEZONE=$(systemsetup -gettimezone 2>/dev/null | awk -F': ' '{print $2}')"
        echo "NETWORK_TIME=$(systemsetup -getusingnetworktime 2>/dev/null | awk -F': ' '{print $2}')"
        echo "TIME_SERVER=$(systemsetup -getnetworktimeserver 2>/dev/null | awk -F': ' '{print $2}')"
        echo ""
        echo "# System Information"
        echo "HOSTNAME=$(hostname)"
        echo "UPTIME=$(uptime)"
        echo "BACKUP_BY=$(whoami)"
    } > "$backup_file"
    
    echo "✅ Backup created: $backup_file"
    log_operation "INFO" "Date/time settings backed up: $backup_file"
}

# Main date/time management function
main() {
    local action="${1:-help}"
    
    case "$action" in
        "status"|"current")
            local format="${2:-all}"
            get_current_datetime "$format"
            ;;
        "set")
            local datetime_input="$2"
            local format_type="${3:-macfleet}"
            local policy="${4:-business_hours}"
            local force="$5"
            
            if [[ -z "$datetime_input" ]]; then
                echo "Usage: $0 set <datetime> [format] [policy] [force]"
                echo "Example: $0 set 120614302023.00 macfleet business_hours"
                return 1
            fi
            
            set_enterprise_datetime "$datetime_input" "$format_type" "$policy" "$force"
            ;;
        "validate")
            local datetime_input="$2"
            local format_type="${3:-macfleet}"
            
            if [[ -z "$datetime_input" ]]; then
                echo "Usage: $0 validate <datetime> [format]"
                return 1
            fi
            
            validate_datetime_format "$datetime_input" "$format_type"
            ;;
        "convert")
            local datetime_input="$2"
            local from_format="$3"
            local to_format="$4"
            
            if [[ -z "$datetime_input" || -z "$from_format" || -z "$to_format" ]]; then
                echo "Usage: $0 convert <datetime> <from_format> <to_format>"
                echo "Available formats: macfleet, iso8601, unix, readable"
                return 1
            fi
            
            convert_datetime_format "$datetime_input" "$from_format" "$to_format"
            ;;
        "schedule")
            local operation="$2"
            local target_datetime="$3"
            local schedule_time="$4"
            local policy="${5:-business_hours}"
            
            if [[ -z "$operation" || -z "$target_datetime" || -z "$schedule_time" ]]; then
                echo "Usage: $0 schedule <operation> <target_datetime> <schedule_time> [policy]"
                echo "Operations: set_datetime, sync_time, backup_datetime"
                return 1
            fi
            
            schedule_datetime_operation "$operation" "$target_datetime" "$schedule_time" "$policy"
            ;;
        "monitor")
            local check_type="${2:-basic}"
            
            monitor_datetime_integrity "$check_type"
            ;;
        "backup")
            local backup_type="${2:-full}"
            
            backup_datetime_settings "$backup_type"
            ;;
        "report")
            local report_type="${2:-summary}"
            
            generate_datetime_report "$report_type"
            ;;
        "help"|*)
            echo "$SCRIPT_NAME v$VERSION"
            echo "Enterprise Date and Time Management"
            echo ""
            echo "Usage: $0 <action> [options]"
            echo ""
            echo "Actions:"
            echo "  status [format]                         - Show current date/time information"
            echo "  set <datetime> [format] [policy] [force] - Set date/time with validation"
            echo "  validate <datetime> [format]            - Validate date/time format"
            echo "  convert <datetime> <from> <to>          - Convert between formats"
            echo "  schedule <op> <datetime> <time> [policy] - Schedule date/time operations"
            echo "  monitor [type]                          - Monitor date/time integrity"
            echo "  backup [type]                           - Backup date/time settings"
            echo "  report [type]                           - Generate date/time reports"
            echo "  help                                    - Show this help message"
            echo ""
            echo "Date/Time Formats:"
            for format in "${!DATE_FORMATS[@]}"; do
                echo "  $format: ${DATE_FORMATS[$format]}"
            done
            echo ""
            echo "Scheduling Policies:"
            for policy in "${!SCHEDULING_POLICIES[@]}"; do
                echo "  $policy: ${SCHEDULING_POLICIES[$policy]}"
            done
            echo ""
            echo "Monitor Types:"
            echo "  basic       - Basic integrity checks"
            echo "  comprehensive - Extended monitoring and validation"
            echo ""
            echo "Report Types:"
            echo "  summary     - Date/time overview (default)"
            echo "  compliance  - Compliance assessment"
            echo "  audit       - Complete audit trail"
            echo ""
            echo "Examples:"
            echo "  $0 set 120614302023.00                 - Set date/time in Macfleet format"
            echo "  $0 set '2023-12-06T14:30:00' iso8601   - Set using ISO 8601 format"
            echo "  $0 convert 120614302023.00 macfleet iso8601 - Convert formats"
            echo "  $0 schedule set_datetime 010108002024.00 '09:00 tomorrow' - Schedule operation"
            echo "  $0 monitor comprehensive               - Full integrity check"
            echo ""
            echo "Features:"
            echo "  • Enterprise-grade date/time management"
            echo "  • Multiple format support and conversion"
            echo "  • Business hours and policy enforcement"
            echo "  • Comprehensive validation and safety checks"
            echo "  • Audit logging and compliance tracking"
            echo "  • Scheduled operations and automation"
            echo "  • Real-time monitoring and integrity checks"
            ;;
    esac
}

# Execute main function with all arguments
main "$@"

Quick Reference Commands

Basic Date/Time Operations

# Check current date/time status
./datetime_manager.sh status

# Set date/time using Macfleet format (Dec 6, 2023 2:30 PM)
./datetime_manager.sh set 120614302023.00

# Set using ISO 8601 format
./datetime_manager.sh set "2023-12-06T14:30:00" iso8601

# Validate date/time format before setting
./datetime_manager.sh validate 120614302023.00 macfleet

Format Conversion

# Convert Macfleet to ISO 8601
./datetime_manager.sh convert 120614302023.00 macfleet iso8601

# Convert ISO 8601 to readable format
./datetime_manager.sh convert "2023-12-06T14:30:00" iso8601 readable

# Convert to Unix timestamp
./datetime_manager.sh convert 120614302023.00 macfleet unix

Enterprise Operations

# Set with business hours policy enforcement
./datetime_manager.sh set 120614302023.00 macfleet business_hours

# Force set outside business hours
./datetime_manager.sh set 120614302023.00 macfleet business_hours true

# Schedule future date/time operation
./datetime_manager.sh schedule set_datetime 010108002024.00 "09:00 tomorrow"

Monitoring and Compliance

# Basic integrity monitoring
./datetime_manager.sh monitor basic

# Comprehensive monitoring
./datetime_manager.sh monitor comprehensive

# Generate compliance report
./datetime_manager.sh report compliance

# Backup current settings
./datetime_manager.sh backup full

Integration Examples

JAMF Pro Integration

#!/bin/bash

# JAMF Pro script for date/time management
# Parameters: $4 = target_datetime, $5 = format, $6 = policy, $7 = force

TARGET_DATETIME="$4"
FORMAT="${5:-macfleet}"
POLICY="${6:-business_hours}"
FORCE="$7"

# Download datetime manager if not present
if [[ ! -f "/usr/local/bin/macfleet_datetime_manager.sh" ]]; then
    curl -o "/usr/local/bin/macfleet_datetime_manager.sh" \
         "https://scripts.macfleet.com/datetime_manager.sh"
    chmod +x "/usr/local/bin/macfleet_datetime_manager.sh"
fi

# Set date/time with enterprise controls
if [[ -n "$TARGET_DATETIME" ]]; then
    /usr/local/bin/macfleet_datetime_manager.sh set \
        "$TARGET_DATETIME" "$FORMAT" "$POLICY" "$FORCE"
    
    # Report status back to JAMF
    if [[ $? -eq 0 ]]; then
        echo "Date/time set successfully: $TARGET_DATETIME"
        exit 0
    else
        echo "Date/time setting failed: $TARGET_DATETIME"
        exit 1
    fi
else
    echo "No target date/time provided"
    exit 1
fi

Automated Compliance Monitoring

#!/bin/bash

# Continuous date/time compliance monitoring
monitor_datetime_compliance() {
    local monitoring_interval=3600  # 1 hour
    local compliance_standard="SOX"
    
    while true; do
        # Run integrity monitoring
        if /usr/local/bin/macfleet_datetime_manager.sh monitor comprehensive &>/dev/null; then
            echo "$(date): Date/time compliance check passed"
        else
            echo "$(date): Date/time compliance issues detected"
            
            # Generate compliance report
            /usr/local/bin/macfleet_datetime_manager.sh report compliance
            
            # Send alert
            send_compliance_alert "Date/time integrity issues" "$compliance_standard"
        fi
        
        sleep "$monitoring_interval"
    done
}

Advanced Features

Scheduled Operations

# Advanced scheduling with business logic
schedule_maintenance_datetime() {
    local target_datetime="$1"
    local maintenance_window="$2"
    
    echo "=== Maintenance Window Date/Time Setting ==="
    echo "Target: $target_datetime"
    echo "Window: $maintenance_window"
    
    # Schedule for next maintenance window
    /usr/local/bin/macfleet_datetime_manager.sh schedule \
        set_datetime "$target_datetime" "$maintenance_window" maintenance_window
}

Compliance Automation

# Automated compliance validation
validate_compliance_requirements() {
    local standard="$1"
    
    echo "=== Compliance Validation ==="
    echo "Standard: $standard"
    
    case "$standard" in
        "SOX")
            # Sarbanes-Oxley requires accurate timestamps
            check_timestamp_accuracy_strict
            verify_audit_trail_completeness
            ;;
        "HIPAA")
            # HIPAA requires time integrity for medical records
            check_medical_timestamp_integrity
            verify_time_source_reliability
            ;;
        "PCI_DSS")
            # PCI DSS requires accurate transaction timestamps
            check_payment_timestamp_accuracy
            verify_time_sync_security
            ;;
    esac
}

Best Practices

  1. Validate all date/time inputs before applying changes
  2. Use business hours policies to prevent unauthorized changes
  3. Implement backup and restore for critical time changes
  4. Monitor time drift continuously with automated alerting
  5. Maintain comprehensive audit logs for compliance
  6. Test format conversions before production deployment
  7. Coordinate with network teams for time synchronization
  8. Document all scheduled operations for operational awareness

This enterprise date and time management system provides comprehensive date/time control with validation, scheduling, compliance tracking, and enterprise-grade automation capabilities for effective MacFleet time management.