Skip to content

Instantly share code, notes, and snippets.

@AUAggy
Created February 9, 2026 10:59
Show Gist options
  • Select an option

  • Save AUAggy/0d3c67cf73e831fbdbf4149bdc935afb to your computer and use it in GitHub Desktop.

Select an option

Save AUAggy/0d3c67cf73e831fbdbf4149bdc935afb to your computer and use it in GitHub Desktop.
Safe rm alias for macOS: Move files to Trash instead of deleting permanently

Safe rm Alias for macOS: Move Files to Trash Instead of Deleting

This script replaces the standard rm command with a safer alternative that moves files to the macOS Trash instead of deleting them permanently. The implementation uses shell functions and aliases to intercept rm calls and redirect them to a custom safe_rm function.

Purpose

The primary purpose is to prevent accidental data loss. The standard rm command deletes files immediately and irreversibly. This implementation moves files to the system Trash (~/.Trash), where they can be recovered if needed.

How It Works

  1. The safe_rm function is defined in ~/.bash_aliases.
  2. The alias rm='safe_rm' command redirects all rm invocations to the safe_rm function.
  3. When rm is called, the function:
    • Verifies the Trash directory exists and creates it if missing
    • Processes each argument passed to rm
    • Checks if each file or directory exists
    • Moves files to ~/.Trash/Files and directories to ~/.Trash
    • Reports success or failure for each operation

Installation

Step 1: Create ~/.bash_aliases

Create or edit ~/.bash_aliases with the following content:

# Safe rm alias: moves files to Trash instead of deleting permanently
# macOS-only implementation with enhanced error handling and safeguards

# Function to move file/directory to Trash
safe_rm() {
    local file
    local trash_dir
    local confirm

    # macOS: use the standard Trash directory
    trash_dir="$HOME/.Trash"

    # Create Trash directory if it doesn't exist
    if [[ ! -d "$trash_dir" ]]; then
        mkdir -p "$trash_dir"
        if [[ $? -ne 0 ]]; then
            echo "Error: Failed to create Trash directory at $trash_dir"
            return 1
        fi
    fi

    # Check if any arguments were provided
    if [[ $# -eq 0 ]]; then
        echo "Usage: safe_rm <file|directory>..."
        return 1
    fi

    # Process each argument
    for file in "$@"; do
        # Check if file exists
        if [[ ! -e "$file" ]]; then
            echo "Error: File not found: $file"
            continue
        fi

        # Check if file is a directory
        if [[ -d "$file" ]]; then
            # For directories, use mv to move entire directory
            if [[ -d "$trash_dir/Files" ]]; then
                mv "$file" "$trash_dir/Files/"
            else
                mv "$file" "$trash_dir/"
            fi
        else
            # For files, move to Files directory
            if [[ -d "$trash_dir/Files" ]]; then
                mv "$file" "$trash_dir/Files/"
            else
                mv "$file" "$trash_dir/"
            fi
        fi

        # Check if mv was successful
        if [[ $? -ne 0 ]]; then
            echo "Error: Failed to move '$file' to Trash"
            continue
        fi

        # Print confirmation
        echo "Moved to Trash: $file"
    done
}

# Create alias for rm to use safe_rm function
alias rm='safe_rm'

# Optional: Add a command to empty the Trash
empty_trash() {
    local trash_dir

    trash_dir="$HOME/.Trash"

    if [[ -d "$trash_dir/Files" ]]; then
        rm -rf "$trash_dir/Files"
        echo "Trash emptied (Files directory)"
    elif [[ -d "$trash_dir" ]]; then
        rm -rf "$trash_dir"
        echo "Trash emptied"
    else
        echo "Trash directory not found"
    fi
}

# Create alias for emptying Trash
alias empty-trash='empty_trash'

# Optional: Add a command to list contents of Trash
list_trash() {
    local trash_dir

    trash_dir="$HOME/.Trash"

    if [[ -d "$trash_dir/Files" ]]; then
        ls -la "$trash_dir/Files"
    elif [[ -d "$trash_dir" ]]; then
        ls -la "$trash_dir"
    else
        echo "Trash directory not found"
    fi
}

# Create alias for listing Trash contents
alias list-trash='list_trash'

Step 2: Create ~/.bash_noninteractive

Create or edit ~/.bash_noninteractive with the following content:

# Configure non-interactive Bash environment to ensure aliases are available

# Enable alias expansion in non-interactive shells
shopt -s expand_aliases

# Source user-defined aliases
source ~/.bash_aliases

Step 3: Configure BASH_ENV

Add the following line to your ~/.bash_profile or ~/.bashrc:

export BASH_ENV=~/.bash_noninteractive

Step 4: Reload Configuration

Reload your shell configuration:

source ~/.bash_aliases

Usage

After sourcing the configuration:

rm file.txt           # Moves file.txt to Trash
rm -rf directory/     # Recursively moves directory/ to Trash
rm *.log              # Moves all .log files to Trash
rm -rf ./foo/*.doc    # Moves all .doc files in ./foo to Trash

Safety Features

  • Error checking: The function validates file existence and directory creation before attempting moves.
  • Success verification: Each mv operation is checked for success.
  • Clear feedback: Each operation reports whether it succeeded or failed.
  • Usage guidance: The function provides help text when no arguments are given.

Additional Commands

The configuration includes three additional aliases:

  • empty-trash: Removes all files from the Trash
  • list-trash: Lists the contents of the Trash
  • safe_rm: The underlying function (not intended for direct use)

Limitations

  • This implementation is macOS-only. It uses the standard macOS Trash location (~/.Trash).
  • The function does not support interactive confirmation prompts by default. The commented-out code provides this functionality if needed.
  • The implementation assumes the user has write permissions to ~/.Trash.
  • The function does not handle symbolic links specially; they are moved as-is.
  • The function does not preserve file metadata (modification times, permissions) during the move.

Security Considerations

  • The script runs with the user's privileges. It cannot access files outside the user's home directory.
  • The script does not log actions. Recovery requires manual inspection of the Trash.
  • The script does not provide versioning or history tracking. Files in the Trash are not recoverable after emptying.

Bypassing the Alias

To use the original rm command when needed:

command rm file.txt    # Uses the original rm command
/bin/rm file.txt       # Direct path to rm binary

The implementation is a direct, functional solution to a common problem: preventing accidental file deletion. It does not claim to be a complete file recovery system, but it provides a simple, reliable way to avoid irreversible data loss in everyday command-line use.

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