Olympus / OM-System in-camera stacking produces many RAW/JPG frames per final JPG. Lightroom doesn't automatically group or separate them, so imports get cluttered. This script separates originals from stacked outputs automatically, so you only need to manually process the photos that actually need your attention.
This script finds the stacked images by looking for .jpg files which have no corresponding raw file. This is the only way I have found to detect which images are the stacked versions - the file sizes / exif data is not unique for photos created with in-camera stacking.
The script has five main modes:
- Copy mode: Finds JPGs without raw files and copies them somewhere else
- Rename mode: Finds those JPGs and renames them in-place by adding " stacked" to the filename
- Stackcopy mode: Copies them to a "stacked" subfolder AND adds " stacked" to their names
- Lightroom mode: Moves the input files of a stack to a dated folder structure and renames the output file in place. Groups based on numeric sequence and timestamp window - the idea is that in-camera focus stacks are renamed and the inputs saved to a separate place, but single shots or focus bracketing isn't moved since you'll want to process those manually.
- Lightroom Import mode: Same as Lightroom mode, but also moves the stacked output JPGs and all remaining files to
~/pictures/Lightroom/YEAR/DATE/- for a complete import workflow.
Plus, you can filter by date, add custom prefixes, and more.
Now supports:
- Multi-threaded copying/moving (
--jobs) for better performance - Atomic file operations - prevents corrupted files from interrupted operations
- Self-healing - automatically recovers from previous interrupted runs
- Cross-device safe move using fallback copy+delete
- Debug mode (
--debug-stacks) for troubleshooting stack detection
Just grab the script and make it executable:
wget https://raw.githubusercontent.com/AlanRockefeller/stackcopy/main/stackcopy.py
chmod +x stackcopy.pyOr clone the whole repo:
git clone https://github.com/AlanRockefeller/stackcopy.git
cd stackcopyRequirements: Python 3.6 or newer. That's it! No extra packages needed.
Here are some real-world scenarios:
./stackcopy.py --copy /photos/Lightroom/2025/2025-07-10/ /photos/stacked-images./stackcopy.py --rename /photos/Lightroom/2025/2025-07-10/./stackcopy.py --stackcopy /photos/Lightroom/2025/2025-07-10/This moves the input files (JPG and ORF) of a stack to a dated folder, and renames the output JPG in place.
./stackcopy.py --lightroom /photos/camera-import/This does everything: moves stack inputs to dated folders, renames stacked outputs, then imports everything (including the renamed stacks and remaining files) to your Lightroom directory structure.
./stackcopy.py --lightroomimport /photos/camera-import/Use 4 parallel workers for faster processing:
./stackcopy.py --lightroomimport /photos/camera-import/ --jobs 4Add --dry to any command:
./stackcopy.py --copy /photos/source /photos/dest --dry./stackcopy.py --copy /photos/camera-import /photos/today-stacked --today./stackcopy.py --stackcopy /photos/mushrooms --prefix "Jackson State Forest"
# Creates files like: "IMG_1234 Jackson State Forest stacked.jpg"./stackcopy.py --lightroom /photos/camera-import/ --debug-stacks --dryHere's what you can do:
--copy SOURCE DEST- Copy orphaned JPGs from SOURCE to DEST--rename [DIR]- Rename orphaned JPGs in-place (default: current directory)--stackcopy [DIR]- Copy to a 'stacked' subfolder with renamed files--lightroom [DIR]- Move stack input files to a dated folder and rename stack output files in place--lightroomimport [DIR]- Same as--lightroom, plus move all remaining files to~/pictures/Lightroom/YEAR/DATE/
--today- Only process files from today--yesterday- Only process files from yesterday--date YYYY-MM-DD- Only process files from a specific date
--prefix PREFIX- Add a custom prefix before " stacked" in filenames--dryor--dry-run- Preview what would happen without making changes-vor--verbose- Show detailed info about each file processed--force- Overwrite existing files without asking--jobs N- Use N parallel workers for copying/moving (faster on large imports)--debug-stacks- Show detailed diagnostic output for stack detection logic
- Atomic operations: Files are written to temporary locations first, then atomically moved to prevent corruption from interruptions
- Self-healing: Automatically detects and replaces 0-byte placeholder files from interrupted previous runs
- Automatically avoids overwriting different files unless
--forceis set - If destination file exists and has identical contents, the operation proceeds safely (removing source for moves)
- All file operations are crash-safe - you'll never end up with partial or corrupted files
The script finds stacked files by looking for JPG files that don't have corresponding raw files:
- It scans your folder for all raw files (ORF, CR2, NEF, ARW, DNG, etc.)
- Then it looks for JPG files that DON'T have a matching raw file
- It ignores files that already have " stacked" in their name (so you can run it multiple times safely)
- Then it does whatever operation you asked for
The matching is case-insensitive, so IMG_1234.JPG will match with img_1234.orf just fine.
In --lightroom and --lightroomimport modes, the script uses advanced logic to identify which input frames belong to each stacked output:
- Numeric sequence detection: Groups files by their numeric stems (e.g., IMG_0100, IMG_0101, IMG_0102)
- Timestamp analysis: Confirms frames were taken within 20 seconds of each other
- Stack size validation: Accepts stacks with 3-15 input frames
- Focus bracket protection: Rejects sequences with more than 15 consecutive frames to avoid moving focus bracketing bursts
Use --debug-stacks with --dry to see exactly why each stack is accepted or rejected.
You just imported photos from your camera and want to separate the stacked JPGs:
# First, see what we're dealing with
./stackcopy.py --copy /photos/import /photos/mushrooms --dry
# Looks good? Run it for real
./stackcopy.py --copy /photos/import /photos/mushrooms
# Want more details?
./stackcopy.py --copy /photos/import /photos/mushrooms --verboseImport everything from your camera card, organize stacks automatically, and move to your Lightroom library:
# Preview what will happen
./stackcopy.py --lightroomimport /media/camera-card/ --dry --verbose
# Looks good? Run with 4 parallel workers for speed
./stackcopy.py --lightroomimport /media/camera-card/ --jobs 4 --verboseThis will:
- Identify stacked outputs (JPGs without RAWs)
- Rename them with " stacked" suffix
- Move their input frames (3-15 RAWs) to
/home/alan/pictures/olympus.stack.input.photos/YEAR/DATE/ - Move the renamed stacked outputs to
~/pictures/Lightroom/YEAR/DATE/ - Move all remaining files to
~/pictures/Lightroom/YEAR/DATE/
If stacks aren't being detected correctly, use debug mode:
./stackcopy.py --lightroom /photos/camera-import/ --debug-stacks --dryThis shows detailed information about:
- Which files are being considered as stack candidates
- Timestamp gaps between frames
- Why stacks are accepted or rejected
- Whether the burst safety check is triggering
If your camera saves HDR composites as JPG-only, mark them clearly:
./stackcopy.py --rename /photos/2025/july --prefix "HDR"You went mushroom hunting and want to just copy the stacked photos you took today:
./stackcopy.py --copy /photos/mushrooms /photos/newstacks --today- Always run with
--dryfirst to see what will happen - The script won't overwrite files unless you use
--force - Files already containing " stacked" are automatically skipped
- You can run the script multiple times safely - it won't double-process files
- The date filters use file modification time (most reliable across platforms)
- Use
--jobs 4or higher for faster processing of large imports (in Lightroom modes or copy operations) - If operations are interrupted, just re-run - the self-healing logic will fix any incomplete files
- Use
--debug-stackswith--dryto understand why certain photo sequences aren't being treated as stacks - In Lightroom Import mode, all files end up in
~/pictures/Lightroom/YEAR/DATE/organized by date
- Version: 1.4
- Date: January 4, 2026
- Author: Alan Rockefeller
- Repository: https://github.com/AlanRockefeller/stackcopy
- License: MIT
MIT License - basically, do whatever you want with it! See the LICENSE file for the legal details.