-
-
Notifications
You must be signed in to change notification settings - Fork 5
Folder Structure
kei uses one directory template per pass: album, smart folder, and unfiled.
[download]
directory = "/photos"
folder_structure = "%Y/%m/%d"
folder_structure_albums = "{album}"
folder_structure_smart_folders = "{smart-folder}"| Pass | Key | Default | Token |
|---|---|---|---|
| Album | folder_structure_albums |
{album} |
{album} |
| Smart folder | folder_structure_smart_folders |
{smart-folder} |
{smart-folder} |
| Unfiled | folder_structure |
%Y/%m/%d |
none |
All three templates accept {library} as the first segment. Standard strftime specifiers such as %Y, %m, and %d are supported. The Python {:%Y/%m/%d} shape is also accepted.
With the default templates:
| Asset type | Path |
|---|---|
Photo in user album Vacation 2024
|
/photos/Vacation 2024/IMG_1234.HEIC |
Photo in smart folder Favorites
|
/photos/Favorites/IMG_1234.HEIC |
| Photo in no user album | /photos/2024/03/15/IMG_1234.HEIC |
Smart-folder passes are off by default. Enable them in [filters].smart_folders.
[filters]
albums = ["all"]
smart_folders = ["none"]
unfiled = trueA photo in N albums writes N on-disk copies when the album template produces distinct paths per {album}. The unfiled pass excludes assets that are in any user album, so albumed assets don't also appear in the unfiled tree.
Explicit album and smart-folder selectors are collection-scoped. A named album or smart folder can download members from shared libraries even when [filters].libraries is still ["primary"]. Unfiled output stays scoped to [filters].libraries.
Changing a path-affecting setting forces a full reconciliation. kei clears stored zone tokens and replans known assets into the new path shape, rather than trusting an incremental token that cannot rediscover files already seen under an old template.
Date hierarchy under each album:
[download]
folder_structure_albums = "{album}/%Y/%m/%d"Only specific albums, no unfiled pass:
[filters]
albums = ["Vacation", "Family"]
unfiled = falseSmart folders with dates:
[filters]
smart_folders = ["all"]
[download]
folder_structure_smart_folders = "{smart-folder}/%Y/%m/%d"When more than one library is in scope, prefix active templates with {library} to keep paths separate:
[filters]
libraries = ["all"]
[download]
folder_structure = "{library}/%Y/%m/%d"
folder_structure_albums = "{library}/{album}"{library} renders as PrimarySync for the personal library or a truncated shared-library zone name such as SharedSync-A1B2C3D4.
-
{library}must be the first path segment when present. -
{album}infolder_structure_albumsmust come before any strftime specifier and after{library}if present. -
{smart-folder}follows the same rule infolder_structure_smart_folders. - Each token may appear at most once per template.
Examples:
| Template | Valid? |
|---|---|
{album} |
yes |
{album}/%Y/%m/%d |
yes |
{library}/{album}/%Y |
yes |
Photos/{album}/%Y |
no |
%Y/{album}/%m |
no |
{album}/%Y/{album} |
no |
Names used as directory components are sanitized to prevent path traversal and invalid directories:
-
..becomes_ - Leading/trailing dots and spaces are stripped
- Windows reserved names are prefixed with
_ - Invalid filesystem characters are removed