Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Pattern Expressions

Pattern expressions define how files are organized in archives. They use {expr} syntax to insert dynamic values based on facts.

Patterns are used in the pattern field of cluster manifests. When you run canon cluster generate, it creates a manifest with a default pattern = "{filename}" that you can customize.

Basic Syntax

Patterns consist of literal path segments and expressions in curly braces:

{content.DateTimeOriginal|year}/{content.DateTimeOriginal|month}/{filename}

This produces paths like: 2024/07/IMG_001.jpg

Fact Keys

Any fact key can be used in a pattern:

  • {source.ext} - File extension
  • {source.mtime} - Modification time
  • {content.Make} - Camera manufacturer (from EXIF)
  • {content.hash.sha256} - Content hash

The content. prefix is optional for content facts, so {Make} is equivalent to {content.Make}.

{scope.rel_path} is not a fact: it is the source’s path below the vantage — the deepest directory containing every scope the manifest records that lies in that source’s own root. With one scope the vantage is that scope. With several, it is the directory they share, so each scope’s own name survives in the result. Scopes in different roots each get their own vantage. cluster generate records the paths it was scoped to; where the manifest records no scope, or none in a source’s root, the pattern is refused rather than guessed.

Modifiers

Transform values using the | syntax. See Facts for the complete list.

{source.mtime|year}           → 2024
{source.mtime|yearmonth}      → 2024-07
{content.hash.sha256|short}   → a1b2c3d4
{source.ext|uppercase}        → JPG

Multiple modifiers can be chained:

{filename|stem|lowercase}     → img_001

Path Accessors

Extract segments from path values using Python-style indexing:

SyntaxMeaning
key[-1]Last segment (filename)
key[0]First segment
key[1:3]Slice segments 1 and 2
key[:-1]All but last segment

Examples with source.rel_path = "photos/2024/vacation/IMG_001.jpg":

{source.rel_path[-1]}         → IMG_001.jpg
{source.rel_path[0]}          → photos
{source.rel_path[1:-1]}       → 2024/vacation
{source.rel_path[-1]|stem}    → IMG_001

Aliases

Aliases provide shorthand for common expressions. Use canon facts --show-aliases to see all available aliases.

AliasExpands To
filenamesource.rel_path[-1]
stemsource.rel_path[-1]|stem
extsource.rel_path[-1]|ext
hashcontent.hash.sha256
hash_shortcontent.hash.sha256|short
idsource.id

Example using aliases:

{hash_short}_{filename}       → a1b2c3d4_IMG_001.jpg

Missing Values

Canon requires all facts used in a pattern to have values for every source. If any source is missing a required fact, canon apply refuses to proceed and reports which facts are missing.

When you run canon cluster generate, the manifest includes comments listing all facts with 100% coverage. These are safe to use in your pattern.

If sources are missing required facts, you can:

  • Filter them out during generation: --where 'DateTimeOriginal?'
  • Import the missing facts via the enrichment pipeline

Common Patterns

# Preserve structure below the manifest's scope
pattern = "{scope.rel_path}"

# Preserve structure below each source's root
pattern = "{source.rel_path}"

# Flat (all files in one directory)
pattern = "{filename}"

# By EXIF capture date
pattern = "{content.DateTimeOriginal|year}/{content.DateTimeOriginal|month}/{filename}"

# By date with hash prefix (collision-safe)
pattern = "{content.DateTimeOriginal|date}/{hash_short}_{filename}"

# By camera
pattern = "{content.Make}/{content.Model}/{filename}"

# By file type and year
pattern = "{source.ext}/{source.mtime|year}/{filename}"