Last active
April 2, 2024 08:33
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Open
Automator
on macOS and select "Folder Action" -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: