Skip to content

Instantly share code, notes, and snippets.

@shikhir-arora
Last active April 2, 2024 08:33
Show Gist options
  • Save shikhir-arora/36efcff1f9890f4b09547e533bc41b3f to your computer and use it in GitHub Desktop.
Save shikhir-arora/36efcff1f9890f4b09547e533bc41b3f to your computer and use it in GitHub Desktop.
macOS Automator / Folder Actions Script to mount, move and automatically trash .dmg files
#!/bin/bash
# Configuration file path
CONFIG_FILE="$HOME/.dmg_script_config"
# Function to setup configuration
setup_configuration() {
echo "Setting up configuration..."
read -r -p "Enter the destination path [$HOME/Applications]: " DESTINATION
DESTINATION=${DESTINATION:-$HOME/Applications} # Default to $HOME/Applications if input is empty
read -r -p "Enter the log file path [$HOME/dmglogfile.log]: " LOG_FILE
LOG_FILE=${LOG_FILE:-$HOME/dmglogfile.log} # Default to $HOME/dmglogfile.log if input is empty
# Save to config file with proper quoting for paths
echo "DESTINATION=\"$DESTINATION\"" > "$CONFIG_FILE"
echo "LOG_FILE=\"$LOG_FILE\"" >> "$CONFIG_FILE"
echo "Configuration saved to $CONFIG_FILE"
echo "Setup completed successfully."
exit 0 # Explicitly exit after setup
}
# Function to log messages
log() {
# Ensure LOG_FILE is defined. If not, default to a temporary log file.
local log_file="${LOG_FILE:-/tmp/dmg_script_temp.log}"
mkdir -p "$(dirname "$log_file")" # Ensure the log directory exists
echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" >> "$log_file"
}
# Function to load and validate configuration
load_and_validate_configuration() {
if [ ! -f "$CONFIG_FILE" ] || [ ! -s "$CONFIG_FILE" ]; then
log "Configuration file not found or empty. Please run the script with --setup to configure."
echo "Configuration file not found or empty. Please run the script with --setup to configure."
exit 1
fi
# shellcheck source=/dev/null
source "$CONFIG_FILE"
log "INFO Configuration file loaded successfully."
if [ -z "$DESTINATION" ] || [ ! -d "$DESTINATION" ]; then
log "Error: Destination is not set or does not exist. Please re-run with --setup."
echo "Error: Destination is not set or does not exist. Please re-run with --setup."
exit 1
fi
if [ -z "$LOG_FILE" ]; then
log "Error: Log file path is not set. Please re-run with --setup."
echo "Error: Log file path is not set. Please re-run with --setup."
exit 1
fi
}
# Helper function for cleanup
cleanup() {
if [ -n "$MOUNT_POINT" ]; then
if ! hdiutil detach "$MOUNT_POINT" >> "$LOG_FILE" 2>&1; then
log "Error unmounting DMG during cleanup"
fi
fi
}
# Function to process DMG files
process_dmg() {
local DMG_PATH="$1"
log "Working directory: $(pwd)"
local DMG_DIR
local DMG_NAME
local MOUNT_POINT=""
DMG_DIR=$(dirname "$DMG_PATH")
DMG_NAME=$(basename "$DMG_PATH")
if ! cd "$DMG_DIR"; then
log "Error: Failed to change directory to $DMG_DIR"
echo "Error: Failed to change directory. Please check the directory path."
exit 1
fi
# Mount the DMG
MOUNT_OUTPUT=$(hdiutil attach "$DMG_NAME" -nobrowse -noautoopen 2>&1)
log "hdiutil attach output: $MOUNT_OUTPUT"
MOUNT_POINT=$(echo "$MOUNT_OUTPUT" | grep "/Volumes" | awk -F '\t' '{ print $3 }' | sed 's/^[[:space:]]*//')
if [ -z "$MOUNT_POINT" ]; then
log "Failed to mount DMG: $DMG_PATH"
return 1
fi
# Destination check
if [ ! -d "$DESTINATION" ]; then
log "Destination directory $DESTINATION does not exist."
cleanup
return 1
fi
# Prioritize .pkg if it exists
PKG_FILE=$(find "$MOUNT_POINT" -name "*.pkg" -maxdepth 1)
if [ -n "$PKG_FILE" ]; then
cp -av "$PKG_FILE" "$DESTINATION" >> "$LOG_FILE" 2>&1
copy_status=$?
if [ $copy_status -ne 0 ]; then
log "Failed to copy .pkg file from DMG: $DMG_PATH"
cleanup
return 1
fi
else
# Application Extraction Attempt
APP_NAME=$(find "$MOUNT_POINT" -name "*.app" -maxdepth 2 | head -n 1)
if [ -n "$APP_NAME" ]; then
cp -a "$APP_NAME" "$DESTINATION/" >> "$LOG_FILE" 2>&1
copy_status=$?
if [ $copy_status -ne 0 ]; then
log "Failed to copy application from DMG: $DMG_PATH"
cleanup
return 1
fi
else
log "Warning: Couldn't determine specific application. Copying all DMG contents."
cp -a "$MOUNT_POINT/"* "$DESTINATION/" >> "$LOG_FILE" 2>&1
copy_status=$?
if [ $copy_status -ne 0 ]; then
log "Failed to copy files from DMG: $DMG_PATH"
cleanup
return 1
fi
fi
fi
# Run cleanup function to un-mount the dmg
cleanup
# Trash DMG (if possible)
if command -v /opt/homebrew/bin/trash >/dev/null 2>&1; then
/opt/homebrew/bin/trash "$DMG_PATH" && killall Finder
else
log "Trash command not found. DMG not deleted: $DMG_PATH"
fi
log "Processed DMG: $DMG_PATH"
}
# Check for --setup argument
if [ "$1" = "--setup" ]; then
setup_configuration
fi
# Pre-load log file path for logging
if [ -f "$CONFIG_FILE" ]; then
# shellcheck source=/dev/null
source "$CONFIG_FILE"
else
echo "Configuration file not found. Please run the script with --setup to configure."
log "WARN Configuration file failed to load successfully."
exit 1
fi
# Load and validate configuration for normal operations
load_and_validate_configuration
# Install cleanup trap
trap cleanup EXIT
# Main processing logic
for file in "$@"; do
if [[ "$file" == *.dmg ]]; then
process_dmg "$file"
fi
done
@shikhir-arora
Copy link
Author

First: download the above script, editing the two variables DESTINATION and LOG_FILE accordingly (make a blank log file and store it somewhere)

Open Automator on macOS and select "Folder Action" -

Screenshot 2024-02-04 at 4 28 12 AM

Select the folder you want the action to monitor for the .dmg files, then search "Run Shell Script" & drag it accordingly - then paste the following into the field:

/Users/username/delete_dmg_after_use.sh "$@"

(note: this should match where the above script is stored)

Then save the workflow and you should be good to go 🙂


Visually this can be seen below:

Screenshot 2024-02-04 at 4 29 16 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment