Script: Automatic Memory Card Import with Terminal (Mac)
The Nerd’s Guide to Lightning-Fast Photo Imports
As a photographer, your time is best spent editing and selecting your best shots, not manually dragging files from your memory card. I wanted to find the fastest and most efficient way to automate the photo import process on Mac, without dealing with Finder, slow transfers, or duplicate images.
The result? A Terminal script that automates the entire workflow:
Imports photos from your memory card instantly
Organizes files neatly by date
Prevents duplicates using hash-based detection
Displays a visual progress bar with ETA
Opens Lightroom (or another app) when the import is finished
Why Use This Method Over Finder or Photo Mechanic?
There are many ways to import photos, such as Finder, Lightroom, or tools like Photo Mechanic, but this Terminal method has unique advantages:
⚡
Speed
Terminal and rsync are much faster than Finder or Photo Mechanic for transferring files.
🤖
Automation
No manual steps; just plug in your memory card, and the script does the rest.
Fewer Errors
No forgotten files, duplicate names, or corrupt transfers.
🔧
Full Control
Decide exactly how and where your files are stored.
💸 FREE!
No need for paid software — just a powerful and reliable script.
This guide will walk you through step-by-step so you can automate your photo import workflow on Mac in just a few minutes! 🚀🔥
Installing the Script
1. Open Terminal (Cmd + Space
, type ‘Terminal’, press Enter).
2. Check if rsync
is installed:
rsync --version
If you have an older version (2.6.9 or lower), update rsync
via Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install rsync
3. Create a script file:
nano ~/import_photos.sh
4. Paste the following script into the file:
#!/bin/bash # 🔥 ASCII Metal Logo 🤘 echo "🔥 WELCOME TO CROP & ROLL IMPORT 🤘🔥" echo "=======================================" echo " \m/ \m/ \m/ \m/ \m/ \m/" echo "=======================================" sleep 1 # Pause for effect 🤘 # ✅ Imported files database for incremental ingest IMPORTED_FILES_DB="/tmp/imported_files.txt" touch "$IMPORTED_FILES_DB" # Ensure the file exists # ✅ Remember last custom name LAST_CUSTOM_NAME_FILE="/tmp/last_custom_name.txt" if [ -f "$LAST_CUSTOM_NAME_FILE" ]; then LAST_CUSTOM_NAME=$(cat "$LAST_CUSTOM_NAME_FILE") else LAST_CUSTOM_NAME="" fi # ✅ Function: Clean up old imported files (older than 90 days) clean_old_imports() { local temp_file="${IMPORTED_FILES_DB}.tmp" local cutoff_date=$(date -v-90d +%Y-%m-%d) awk -v cutoff="$cutoff_date" '$1 >= cutoff' "$IMPORTED_FILES_DB" > "$temp_file" mv "$temp_file" "$IMPORTED_FILES_DB" } # ✅ Function: Check available disk space before import check_disk_space() { AVAILABLE_SPACE=$(df -k "$HOME" | awk 'NR==2 {print $4}') AVAILABLE_GB=$((AVAILABLE_SPACE / 1024 / 1024)) if [[ $AVAILABLE_GB -lt 10 ]]; then echo "⚠️ Warning: Only $AVAILABLE_GB GB free on your disk!" osascript -e 'display notification "Low disk space! Only '$AVAILABLE_GB'GB left." with title "Photo Import"' fi if [[ $AVAILABLE_GB -lt 2 ]]; then echo "❌ ERROR: Not enough space ($AVAILABLE_GB GB). Import stopped." osascript -e 'display notification "Not enough space! Import stopped." with title "Photo Import"' exit 1 fi } # ✅ Function: Detect all SD cards detect_sd_cards() { SD_CARDS=() for volume in /Volumes/*; do if [[ -d "$volume/DCIM" ]]; then SD_CARDS+=("$volume/DCIM") fi done } # ✅ Function: Check if a file has already been imported file_already_imported() { local file_hash="$1" grep -q "$file_hash" "$IMPORTED_FILES_DB" } # ✅ Function: Add file hash to database after successful import add_file_to_db() { local file_hash="$1" echo "$(date +%Y-%m-%d) $file_hash" >> "$IMPORTED_FILES_DB" } # ✅ Function: Start import of a single SD card import_sd_card() { SD_PATH="$1" echo "🚀 Starting import from: $SD_PATH" # ✅ Ask for a custom name (suggest last used name) echo "📝 Enter a custom name (or press Enter to keep '$LAST_CUSTOM_NAME'):": read CUSTOM_NAME if [[ -z "$CUSTOM_NAME" ]]; then CUSTOM_NAME=$LAST_CUSTOM_NAME fi echo "$CUSTOM_NAME" > "$LAST_CUSTOM_NAME_FILE" check_disk_space clean_old_imports DEST="$HOME/Pictures/RAW" mkdir -p "$DEST" for file in "$SD_PATH"/*; do if [[ -f "$file" ]]; then file_hash=$(md5 -q "$file") # Compute hash # ✅ Check if file has already been imported if file_already_imported "$file_hash"; then echo "⚠️ Skipping: $(basename "$file") (Already imported)" continue fi photo_date=$(stat -f "%Sm" -t "%Y-%m-%d" "$file") photo_time=$(stat -f "%Sm" -t "%H%M" "$file") basename=$(basename "$file") photo_dest="$DEST/$photo_date" mkdir -p "$photo_dest" newname="${photo_date}_${photo_time}_${CUSTOM_NAME}_$(basename "$file")" /opt/homebrew/bin/rsync -a "$file" "$photo_dest/$newname" add_file_to_db "$file_hash" fi done echo -e "\n✅ Import complete! 🎸🔥" echo "💿 Ejecting SD card..." diskutil unmountDisk "$SD_PATH" } # ✅ Main loop to allow multiple card imports while true; do detect_sd_cards for SD_PATH in "${SD_CARDS[@]}"; do import_sd_card "$SD_PATH" done # ✅ Ask user if they want to import another card echo "🔄 Do you want to import another memory card? (y/n)" read answer if [[ "$answer" != "y" ]]; then break fi echo "📢 Please insert the next memory card and press Enter." read sleep 2 done # ✅ Launch Lightroom only after all cards are done! echo "🚀 All cards have been imported! Launching Lightroom..." open -a "Adobe Lightroom Classic" echo "✅ Script completed and exited!" exit 0
Key Features and Customization
Changing the Destination Folder
By default, photos are saved in:
DEST="$HOME/Pictures/RAW"
To change this, modify the path. Example for an external drive:
DEST="/Volumes/ExternalDrive/Photography/RAW"
If you use cloud storage (e.g., OneDrive, Dropbox, Google Drive), you can change it like this:
DEST="$HOME/Library/CloudStorage/OneDrive/Photography/RAW"
💡 Make sure the destination folder exists, or the script will create it automatically.
Skipping Duplicate Files
The script prevents duplicate imports by checking file hashes (unique digital fingerprints for each file). This means renaming a file doesn’t trick the system, and exact duplicates will be skipped.
✅ How it works: Before importing a file, the script calculates its MD5 hash and checks if it’s already in the import history (imported_files.txt
). If a file with the same hash exists, it is skipped.
✅ Code snippet from the script:
file_already_imported() { local file_hash="$1" grep -q "$file_hash" "$IMPORTED_FILES_DB" }
✅ If you want to reset the history and re-import everything: Run this command before your next import:
💡 The script automatically removes old import records older than 90 days, so you don’t need to manually clean up.
Changing the App That Opens After Import
The script opens Lightroom by default:
open -a "Adobe Lightroom Classic"
To open Capture One, change it to:
open -a "Capture One"
Or remove the line entirely if you don't want any app to open.
Adjusting the Import Naming Structure
By default, your files are renamed as follows:
YYYY-MM-DD_HHMM_CustomName_OriginalFilename
Example:
2025-02-06_1530_Concert-Metallica_IMG_4567.CR3
If you want to change the structure, modify this line in the script:
newname="${photo_date}_${photo_time}_${CUSTOM_NAME}_$(basename "$file")"
For example, if you want to include the photographer’s name first:
newname="Wouter-Vellekoop_${photo_date}_${photo_time}_${CUSTOM_NAME}_$(basename "$file")"
Making the Script Run
Running the Script Manually
Whenever you insert a memory card, open Terminal and run:
~/import_photos.sh
This will start the import process immediately.
Create a Terminal Alias
Create a shortcut by adding this line to ~/.zshrc
:
alias import="~/import_photos.sh"
Create a Mac App with Automator
Open Automator and choose
Application
.Add a Shell Script action.
Paste:
~/import_photos.sh
4. Save as, and you got your own application!
Conclusion:
With this script, importing photos on Mac becomes a seamless and fully automated process. No more manually dragging and dropping files, no more duplicate images filling up your storage, and no more waiting around—just plug in your memory card, and let the script handle everything. 🚀
By leveraging rsync for high-speed transfers, hash-based duplicate detection, and a structured folder organization, this workflow ensures that every import is fast, reliable, and optimized for photographers. Whether you shoot concerts, events, or portraits, this script will streamline your Mac photography workflow and eliminate unnecessary steps.
Key features that make this the best way to import photos on Mac:
✅ Fastest memory card import method using rsync
✅ Prevents duplicate images with hash-based verification
✅ Automates file renaming and organization
✅ Customizable progress bar and import settings
✅ Works with Lightroom, Capture One, or any editing software
This script is ideal for professional photographers looking for the fastest way to import and organize photos on Mac. Whether you’re dealing with hundreds or thousands of RAW files, it ensures a non-destructive, efficient, and fully automated workflow.
💡 Want to make this even better? If you have questions, feature requests, or feedback, feel free to reach out! I’d love to hear how this script is improving your workflow and what features you’d like to see next. 🚀🔥