Look first
Run the dry run over the tree so the numbers in the real run are not a surprise: scrubpony -n -r ~/Pictures/to-upload. Nothing is written.
The common case, and the one the tool is shaped around. Nobody scrubs one photo — they scrub the folder they are about to upload.
Run the dry run over the tree so the numbers in the real run are not a surprise: scrubpony -n -r ~/Pictures/to-upload. Nothing is written.
The two trees may not nest in either direction, and that is refused rather than allowed to loop — an output directory inside the source means the second run reads what the first one wrote, and a source inside the output means scrubbing the scrubbed copies. Pick something adjacent, like ~/clean.
-r recurses, -d mirrors the source tree under the target with filenames unchanged. Your originals are never touched. This is the mode to reach for on a whole library — sibling .scrubbed.jpg output is fine for one photo and unpleasant across four thousand, where it leaves a tree of double the size with two versions of everything interleaved.
$ scrubpony -r -d ~/clean ~/Pictures/to-upload scrubpony: 834 scrubbed, 366 already clean, 3 not JPEG, 4 skipped, 2 failed scrubpony: 1148605 bytes of metadata removed scrubpony: 257 carried GPS coordinates scrubpony: 266 rely on EXIF orientation to display correctly (266 preserved)
The counts are the point. 257 carried GPS coordinates is the line people react to, and it prints even when nothing went wrong. If anything failed, the per-file error went to stderr with the path named, and nothing was written for that file.
The clean tree is at ~/clean with the same structure and the same filenames. Upload from there.
scrubpony --check -r ~/clean exits 0 and prints nothing about individual files.~/Pictures/to-upload have unchanged modification times.~/clean still display the right way up.Symbolic links, which are never followed; non-regular files; anything deeper than 64 levels; and, on a second pass, the tool's own outputs and any leftover temporaries. Add -v to have them named.
The path was printed to stderr with the reason, and nothing was written for it. A failure on one file never stops the run — the exit code reflects the worst outcome, but only after every other file has been attempted.
Yes. A second pass skips the outputs the first one wrote instead of producing photo.scrubbed.scrubbed.jpg.
Strips identifying metadata out of JPEGs without touching a pixel. C99, no dependencies beyond libc, macOS and Linux, MIT-licensed.