FileFerry is a small CLI that organizes image and video files into target folders using metadata and filename patterns.
- Scan one or more source directories (profiles) for media files.
- Extract metadata from filenames, EXIF (images) or ffprobe (videos) when available.
- Render a per-profile target path template and move files (dry-run by default).
Build and dry-run with your config file:
go build -o fileferry .
./fileferry config.yaml # dry-run: shows what would move
./fileferry config.yaml --ack # actually move filesExample (anonymized) config.yaml excerpt:
profiles:
Videos:
sources:
- path: /path/to/videos
recurse: true
types: [video]
patterns:
- "{meta.taken.date} {meta.taken.time}.mkv"
- "{meta.taken.date}-{meta.taken.time}.mkv"
target:
path: /organized/videos/{meta.taken.year}/{meta.taken.date}/{meta.taken.datetime}.{file.extension}
Pictures:
sources:
- path: /path/to/pictures
recurse: false
types: [image]
target:
path: /organized/pictures/{meta.taken.year}/{meta.taken.date}/{meta.taken.datetime}.{file.extension}profilesis a map of profile names -> profile config.- A
ProfileConfigcontains:sources(list), optionalpatterns(filename patterns used to extract metadata), andtarget.path(template used to build destination path). SourceConfighaspath,recurse,typesand optionalfilenames.
{meta.taken.year},{meta.taken.date},{meta.taken.datetime}{meta.camera.maker},{meta.camera.model}{file.extension}(no leading dot)
Notes: filename patterns are anchored and must match the filename exactly (e.g. 2025-06-02 15-21-02.mkv). Patterns support tokens like {meta.taken.date} and {meta.taken.time} which map to regex rules.
Some tokens support custom format specifiers to match different time formats. Format specifiers are specified after a colon in the token (e.g., {meta.taken.time:hhmmss}).
Supported format specifiers for {meta.taken.time}:
hh-mm-ss(default): Time in formatHH-MM-SS(e.g.,22-22-12)hhmmss: Time in compact formatHHMMSS(e.g.,222212)hhmm: Time in hour-minute formatHHMM(e.g.,1530)
Example using custom format specifiers:
profiles:
Pictures:
sources:
- path: /path/to/pictures
recurse: false
types: [image]
patterns:
- "Still {meta.taken.date} {meta.taken.time:hhmmss}_1.1.1.jpg"
target:
path: /organized/{meta.taken.year}/{meta.taken.date}/{meta.taken.datetime}.{file.extension}This pattern matches filenames like Still 2026-01-23 222212_1.1.1.jpg where the time 222212 represents 22:22:12.
go build -o fileferry .
gofmt -d .
go vet ./...ffprobe(from ffmpeg) improves video metadata extraction.exiftoolimproves image metadata extraction.
- The config loader validates that each profile has a non-empty
target.pathand that source paths are unique across profiles.
Short and to the point — see the source and config.yaml for details.