How to Manage a Photo Archive with fslint

The Archive Layout

Photos/
├── 2022/
│   ├── 2022-03-15 Spring Hiking/
│   │   ├── IMG_4821.jpg
│   │   └── VID_001.mp4
│   └── 2022-12-24 Christmas Party/
│       ├── DSC_9901.jpg
│       └── clip.mov
├── 2023/
│   └── 2023-06-01 Beach Trip/
│       └── ...
└── 2024/
    └── ...

The rules are:

  1. Year folders — the top level contains only directories named YYYY.
  2. Event folders — inside each year, every directory is named YYYY-MM-DD Description.
  3. Media files — inside each event folder, only .jpg, .mp4, .mov, and .png files are allowed.

fslint checks one directory at a time (no recursion), so you target each level with shell globs.

Validate the Entire Archive

A series of one-liners, no loops:

# Year folders must have a date prefix
fslint --isfolder --dateprefix ./Photos/

# Event folders inside any year must have a date prefix
fslint --isfolder --dateprefix ./Photos/*/

# Files inside event folders must be jpg, mp4, mov, or png
fslint --isfile --isext jpg ./Photos/*/*/
fslint --isfile --isext mp4 ./Photos/*/*/
fslint --isfile --isext mov ./Photos/*/*/
fslint --isfile --isext png ./Photos/*/*/

Each command prints paths that violate the rule and exits 1 if any are found, 0 otherwise. Run them sequentially and check $? after each one.

Validate a Single Year

fslint --isfolder --dateprefix ./Photos/2023/
fslint --isfile --isext jpg ./Photos/2023/*/
fslint --isfile --isext mp4 ./Photos/2023/*/
fslint --isfile --isext mov ./Photos/2023/*/
fslint --isfile --isext png ./Photos/2023/*/

Fix Misnamed Folders Before Validating

If event folders were created by a phone or camera app without ISO dates, run the appropriate fixer first:

python src/fslint/fix_iphone.py --execute ./Photos/2023/
python src/fslint/fix_android_photo.py --execute ./Photos/2023/

Then re-run the validation commands above to confirm everything passes.

Use in CI or Cron

Because fslint exits 0 on success and 1 on failure, chain the commands directly:

# crontab entry — run weekly, email output on failure
0 3 * * 0 { \
  fslint --isfolder --dateprefix ./Photos/ && \
  fslint --isfolder --dateprefix ./Photos/*/ && \
  fslint --isfile --isext jpg ./Photos/*/*/ && \
  fslint --isfile --isext mp4 ./Photos/*/*/ && \
  fslint --isfile --isext mov ./Photos/*/*/ && \
  fslint --isfile --isext png ./Photos/*/*/; \
} || mail -s "Photo archive violations" admin@example.com