Introduction

Every photo you take contains more than meets the eye.

Hidden inside are EXIF metadata tags — GPS coordinates, camera serial numbers, timestamps, copyright notices, and even software info. While useful for photographers, this data can leak way more about you than you’d expect when you post a picture online.

So I wanted a simple tool that I could use on my own photos. My old process was a mess — a half-remembered crib sheet, three separate commands, and too much context-switching. I hated it. So I built something better. A robust, flexible little CLI tool for managing image metadata. I find it useful enough that I keep using it and polishing it.


My best elevator pitch:

Metaclean is a small, pipe-friendly CLI tool that scans images for metadata and safely strips it away, with the right defaults so you won’t accidentally destroy your originals.

Perfect for:

  • Preparing photos for blog posts or public sharing
  • Stripping GPS coordinates from family photos
  • Cleaning a folder before archiving or handing off to clients

🔗 View metaclean on GitHub


Quickstart

# Scan for metadata
metaclean --scan photo.jpg

# Strip metadata (safe copy in ~/Pictures/cleaned/)
metaclean --strip photo.jpg

Works with JPG, PNG, WebP and TIFF

Features

  • Safe by default: writes copies with _clean added to the filename unless --inplace is specified
  • Scan EXIF metadata including GPS, camera details, and copyright information
  • Strip all metadata by default, rebuilding clean EXIF from scratch
  • Add copyright tags with --copyright
  • Preserve specific tags with --keep-date, --keep-orientation, --keep-icc, --keep-dpi
  • Pipe-friendly: works with find, xargs, fd, and similar tools

Usage

metaclean (--scan | --strip) [OPTIONS] [FILES…]

Options:

  • --scan — Scan and report metadata.
  • --strip — Strip metadata (writes clean copies unless --inplace).
  • --positives — Only show files that contain metadata (scan mode).
  • --show-gps — Expand GPS info when scanning.
  • --inplace — Overwrite originals (safe atomic replace).
  • --outdir DIR — Directory for cleaned files (default: ~/Pictures/cleaned).
  • --copyright TEXT — Add a copyright tag.
  • --keep-date — Preserve DateTimeOriginal tag.
  • --keep-orientation — Preserve orientation tag (pixels still corrected if not kept).
  • --keep-icc — Preserve ICC profile.
  • --keep-dpi — Preserve DPI.
  • --force — Process first frame of animated images (otherwise skipped).
  • --quality N — JPEG quality (default: 95).
  • --progressive 0|1 — Force progressive JPEG encoding on (1) or off (0).

# Scan a single image for metadata
metaclean --scan photo.jpg

# Scan only images that have metadata (quiet mode)
metaclean --scan --positives ~/Pictures/*.jpg

# Strip metadata from a single file (safe copy in ~/Pictures/cleaned/)
metaclean --strip photo.jpg

# Strip metadata and overwrite originals (use with care)
metaclean --strip --inplace *.jpg

# Strip metadata but keep the original date and orientation tags
metaclean --strip --keep-date --keep-orientation *.jpg

# Add a copyright tag to your images
metaclean --strip --copyright "© forfaxx" ~/Photos/*.jpg

# Find all JPGs with metadata, then strip them in-place
find ~/Pictures -name '*.jpg' \
  | metaclean --scan --positives \
  | metaclean --strip --inplace

Example Output

forfaxx@shinobi ]:/mnt/d/sort
$ metaclean --scan misc040.jpg
=== Metadata for misc040.jpg ===
ResolutionUnit: 2
ExifOffset: 196
Make: Canon
Model: Canon PowerShot G3
Orientation: 1
DateTime: 2005:11:02 19:05:35
YCbCrPositioning: 1
XResolution: 180.0
YResolution: 180.0

forfaxx@shinobi ]:/mnt/d/sort
$ metaclean --strip --inplace misc040.jpg
[OK] Stripped metadata IN PLACE → misc040.jpg

forfaxx@shinobi ]:/mnt/d/sort
$ metaclean --scan misc040.jpg
[INFO] No EXIF metadata found in misc040.jpg

Original image with EXIF metadata present
Before: misc040-exif.jpg — original file with EXIF (camera model, timestamp, etc.).

Cleaned image with EXIF metadata removed
After: misc040.jpg — cleaned by metaclean (no EXIF; pixels preserved).

ThumbsPlus side by side metadata view
Before and After view in ThumbsPlus

Using metaclean in a pipeline or script

metaclean is designed to work well in pipelines and scripts. A few examples:

Show me files with metadata (dry-run)

# Scan repo images and list only files that contain metadata
git ls-files -z -- '*.jpg' '*.jpeg' '*.png' '*.webp' '*.tif' '*.tiff' \
| xargs -0 metaclean --scan --positives \
| tee /tmp/metaclean_positives.txt

echo "Files with metadata: $(wc -l < /tmp/metaclean_positives.txt)"

In-place strip of only what’s staged for commit (pre-commit friendly)

# Safe atomic replace (your script’s default behavior) on staged images
git diff --cached --name-only -z -- '*.jpg' '*.jpeg' '*.png' '*.webp' '*.tif' '*.tiff' \
| xargs -0 metaclean --strip --inplace --keep-icc --keep-dpi

# Re-stage files that changed (helps if hook runs before commit)
git add --update

One-liner to strip everything under current directory into ~/Pictures/cleaned

find . -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \
                 -o -iname '*.webp' -o -iname '*.tif' -o -iname '*.tiff' \) -print0 \
| xargs -0 metaclean --strip --outdir "${HOME}/Pictures/cleaned"
  1. Makefile target for “pre-publish:clean-images”
# Makefile
IMGS := $(shell git ls-files -- '*.jpg' '*.jpeg' '*.png' '*.webp' '*.tif' '*.tiff')
OUT  := static/img-clean

.PHONY: images-clean
images-clean:
	@mkdir -p $(OUT)
	@echo "→ Scanning and cleaning images into $(OUT)…"
	@printf '%s\0' $(IMGS) \
	| xargs -0 metaclean --scan --positives \
	| metaclean --strip --keep-icc --keep-dpi --outdir $(OUT)
	@echo "✓ Done."

# Optional: fold into your publish chain
publish: images-clean
	./sync-adminjitsu.sh

Conclusion

Whether you’re cleaning up a single selfie or prepping an archive for public release, metaclean has your back.

Have a neat pipeline or trick?

PRs and issues welcome! Or email me: feedback@adminjitsu.com