diff --git a/API_README.md b/API_README.md index b9da0fb6..418e13cc 100644 --- a/API_README.md +++ b/API_README.md @@ -1727,7 +1727,7 @@ In its simplest form, a template statement has the form: `"{template_field}"`, f Template statements may contain one or more modifiers. The full syntax is: -`"pretext{delim+template_field:subfield|filter(path_sep)[find,replace] conditional?bool_value,default}posttext"` +`"pretext{delim+template_field:subfield(field_arg)|filter[find,replace] conditional?bool_value,default}posttext"` Template statements are white-space sensitive meaning that white space (spaces, tabs) changes the meaning of the template statement. @@ -1748,6 +1748,8 @@ e.g. if Photo keywords are `["foo","bar"]`: `:subfield`: Some templates have sub-fields, For example, `{exiftool:IPTC:Make}`; the template_field is `exiftool` and the sub-field is `IPTC:Make`. +`(field_arg)`: optional arguments to pass to the field; for example, with `{folder_album}` this is used to pass the path separator used for joining folders and albums when rendering the field (default is "/" for `{folder_album}`). + `|filter`: You may optionally append one or more filter commands to the end of the template field using the vertical pipe ('|') symbol. Filters may be combined, separated by '|' as in: `{keyword|capitalize|parens}`. Valid filters are: @@ -1762,6 +1764,18 @@ Valid filters are: - `brackets`: Enclose value in brackets, e.g. 'value' => '[value]' - `shell_quote`: Quotes the value for safe usage in the shell, e.g. My file.jpeg => 'My file.jpeg'; only adds quotes if needed. - `function`: Run custom python function to filter value; use in format 'function:/path/to/file.py::function_name'. See example at https://github.com/RhetTbull/osxphotos/blob/master/examples/template_filter.py +- `split(x)`: Split value into a list of values using x as delimiter, e.g. 'value1;value2' => ['value1', 'value2'] if used with split(;). +- `autosplit`: Automatically split delimited string into separate values; will split strings delimited by comma, semicolon, or space, e.g. 'value1,value2' => ['value1', 'value2']. +- `chop(x)`: Remove x characters off the end of value, e.g. chop(1): 'Value' => 'Valu'; when applied to a list, chops characters from each list value, e.g. chop(1): ['travel', 'beach']=> ['trave', 'beac']. +- `chomp(x)`: Remove x characters from the beginning of value, e.g. chomp(1): ['Value'] => ['alue']; when applied to a list, removes characters from each list value, e.g. chomp(1): ['travel', 'beach']=> ['ravel', 'each']. +- `sort`: Sort list of values, e.g. ['c', 'b', 'a'] => ['a', 'b', 'c']. +- `rsort`: Sort list of values in reverse order, e.g. ['a', 'b', 'c'] => ['c', 'b', 'a']. +- `reverse`: Reverse order of values, e.g. ['a', 'b', 'c'] => ['c', 'b', 'a']. +- `uniq`: Remove duplicate values, e.g. ['a', 'b', 'c', 'b', 'a'] => ['a', 'b', 'c']. +- `join(x)`: Join list of values with delimiter x, e.g. join(:): ['a', 'b', 'c'] => 'a:b:c'; the DELIM option functions similar to join(x) but with DELIM, the join happens before being passed to any filters. +- `append(x)`: Append x to list of values, e.g. append(d): ['a', 'b', 'c'] => ['a', 'b', 'c', 'd']. +- `prepend(x)`: Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c'] => ['d', 'a', 'b', 'c']. +- `remove(x)`: Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] => ['a', 'c']. e.g. if Photo keywords are `["FOO","bar"]`: @@ -1774,8 +1788,6 @@ e.g. if Photo description is "my description": - `"{descr|titlecase}"` renders to: `"My Description"` -`(path_sep)`: optional path separator to use when joining path-like fields, for example `{folder_album}`. Default is "/". - e.g. If Photo is in `Album1` in `Folder1`: - `"{folder_album}"` renders to `["Folder1/Album1"]` @@ -1818,7 +1830,7 @@ This can be used to rename files as well, for example: This renames any photo that is a favorite as 'Favorite-ImageName.jpg' (where 'ImageName.jpg' is the original name of the photo) and all other photos with the unmodified original name. -`?bool_value`: Template fields may be evaluated as boolean (True/False) by appending "?" after the field name (and following "(path_sep)" or "[find/replace]". If a field is True (e.g. photo is HDR and field is `"{hdr}"`) or has any value, the value following the "?" will be used to render the template instead of the actual field value. If the template field evaluates to False (e.g. in above example, photo is not HDR) or has no value (e.g. photo has no title and field is `"{title}"`) then the default value following a "," will be used. +`?bool_value`: Template fields may be evaluated as boolean (True/False) by appending "?" after the field name (and following "(field_arg)" or "[find/replace]". If a field is True (e.g. photo is HDR and field is `"{hdr}"`) or has any value, the value following the "?" will be used to render the template instead of the actual field value. If the template field evaluates to False (e.g. in above example, photo is not HDR) or has no value (e.g. photo has no title and field is `"{title}"`) then the default value following a "," will be used. e.g. if photo is an HDR image, @@ -1848,6 +1860,16 @@ Either or both bool_value or default (False value) may be empty which would resu If you want to include "{" or "}" in the output, use "{openbrace}" or "{closebrace}" template substitution. e.g. `"{created.year}/{openbrace}{title}{closebrace}"` would result in `"2020/{Photo Title}"`. + +**Variables** + +You can define variables for later use in the template string using the format `{var:NAME,VALUE}`. Variables may then be referenced using the format `%NAME`. For example: `{var:foo,bar}` defines the variable `%foo` to have value `bar`. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the "pipe" (`|`) character is not allowed in a find/replace pair but you can get around this limitation like so: `{var:pipe,{pipe}}{title[-,%pipe]}` which replaces the `-` character with `|` (the value of `%pipe`). + +Variables can also be referenced as fields in the template string, for example: `{var:year,created.year}{original_name}-{%year}`. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: `{var:name,Katie}{person contains {%name}?{%name},Not-{%name}}`. + +If you need to use a `%` (percent sign character), you can escape the percent sign by using `%%`. You can also use the `{percent}` template field where a template field is required. For example: + +`{title[:,%%]}` replaces the `:` with `%` and `{title contains Foo?{title}{percent},{title}}` adds `%` to the title if it contains `Foo`. The following template field substitutions are availabe for use the templating system. @@ -1927,8 +1949,8 @@ cog.out(get_template_field_table()) |{moment}|The moment title of the photo| |{uuid}|Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'| |{id}|A unique number for the photo based on its primary key in the Photos database. A sequential integer, e.g. 1, 2, 3...etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{id:05d}' which results in 00001, 00002, 00003...etc. | -|{album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album. Only valid when used in a '--filename' template and only when '{album}' or '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{album_seq}_{original_name}"'. To start counting at a value other than 0, append append a period and the starting value to the field name. For example, to start counting at 1 instead of 0: '{album_seq.1}'. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{album_seq:05d}' which results in 00000, 00001, 00002...etc. This may result in incorrect sequences if you have duplicate albums with the same name; see also '{folder_album_seq}'.| -|{folder_album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album and folder path. Only valid when used in a '--filename' template and only when '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{folder_album_seq}_{original_name}"'. To start counting at a value other than 0, append append a period and the starting value to the field name. For example, to start counting at 1 instead of 0: '{folder_album_seq.1}' May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{folder_album_seq:05d}' which results in 00000, 00001, 00002...etc. This may result in incorrect sequences if you have duplicate albums with the same name in the same folder; see also '{album_seq}'.| +|{album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album. Only valid when used in a '--filename' template and only when '{album}' or '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{album_seq}_{original_name}"'. To start counting at a value other than 0, append append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{album_seq(1)}'. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name; see also '{folder_album_seq}'.| +|{folder_album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album and folder path. Only valid when used in a '--filename' template and only when '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{folder_album_seq}_{original_name}"'. To start counting at a value other than 0, append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{folder_album_seq(1)}' May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{folder_album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{folder_album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name in the same folder; see also '{album_seq}'. | |{comma}|A comma: ','| |{semicolon}|A semicolon: ';'| |{questionmark}|A question mark: '?'| @@ -1943,7 +1965,7 @@ cog.out(get_template_field_table()) |{lf}|A line feed: '\n', alias for {newline}| |{cr}|A carriage return: '\r'| |{crlf}|a carriage return + line feed: '\r\n'| -|{osxphotos_version}|The osxphotos version, e.g. '0.49.9'| +|{osxphotos_version}|The osxphotos version, e.g. '0.50.0'| |{osxphotos_cmd_line}|The full command line used to run osxphotos| |{album}|Album(s) photo is contained in| |{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder| @@ -1964,6 +1986,7 @@ cog.out(get_template_field_table()) |{detected_text}|List of text strings found in the image after performing text detection. Using '{detected_text}' will cause osxphotos to perform text detection on your photos using the built-in macOS text detection algorithms which will slow down your export. The results for each photo will be cached in the export database so that future exports with '--update' do not need to reprocess each photo. You may pass a confidence threshold value between 0.0 and 1.0 after a colon as in '{detected_text:0.5}'; The default confidence threshold is 0.75. '{detected_text}' works only on macOS Catalina (10.15) or later. Note: this feature is not the same thing as Live Text in macOS Monterey, which osxphotos does not yet support.| |{shell_quote}|Use in form '{shell_quote,TEMPLATE}'; quotes the rendered TEMPLATE value(s) for safe usage in the shell, e.g. My file.jpeg => 'My file.jpeg'; only adds quotes if needed.| |{strip}|Use in form '{strip,TEMPLATE}'; strips whitespace from begining and end of rendered TEMPLATE value(s).| +|{format}|Use in form, '{format:TYPE:FORMAT,TEMPLATE}'; converts TEMPLATE value to TYPE then formats the value using Python string formatting codes specified by FORMAT; TYPE is one of: 'int', 'float', or 'str'. For example, '{format:float:.1f,{exiftool:EXIF:FocalLength}}' will format focal length to 1 decimal place (e.g. '100.0'). | |{function}|Execute a python function from an external file and use return value as template substitution. Use in format: {function:file.py::function_name} where 'file.py' is the name of the python file and 'function_name' is the name of the function to call. The function will be passed the PhotoInfo object for the photo. See https://github.com/RhetTbull/osxphotos/blob/master/examples/template_function.py for an example of how to implement a template function.| diff --git a/README.md b/README.md index fb82a29d..5f39e385 100644 --- a/README.md +++ b/README.md @@ -402,6 +402,14 @@ A powerful feature of Photos is that it uses machine learning algorithms to auto `osxphotos export /path/to/export --exiftool --keyword-template "{label}"` +#### Removing a keyword during export + +If some of your photos contain a keyword you do not want to be added to the exported file with `--exiftool`, you can use the template system to remove the keyword from the exported file. For example, if you want to remove the keyword "MyKeyword" from all your photos: + +`osxphotos export /path/to/export --exiftool --keyword-template "{keyword|remove(MyKeyword)}" --replace-keywords` + +In this example, `|remove(MyKeyword)` is a filter which removes `MyKeyword` from the keyword list of every photo being processed. The `--replace-keywords` option instructs osxphotos to replace the keywords in the exported file with the filtered keywords from `--keyword-template`. + **Note**: When evaluating templates for `--directory` and `--filename`, osxphotos inserts the automatic default value "_" for any template field which is null (empty or blank). This is to ensure that there's never a null directory or filename created. For metadata templates such as `--keyword-template`, osxphotos does not provide an automatic default value thus if the template field is null, no keyword would be created. Of course, you can provide a default value if desired and osxphotos will use this. For example, to add "nolabel" as a keyword for any photo that doesn't have labels: `osxphotos export /path/to/export --exiftool --keyword-template "{label,nolabel}"` @@ -1405,7 +1413,7 @@ for example "{title}" which would resolve to the title of the photo. Template statements may contain one or more modifiers. The full syntax is: -"pretext{delim+template_field:subfield|filter(path_sep)[find,replace] +"pretext{delim+template_field:subfield(field_arg)|filter[find,replace] conditional?bool_value,default}posttext" Template statements are white-space sensitive meaning that white space @@ -1435,6 +1443,11 @@ full list of template fields. :subfield: Some templates have sub-fields, For example, {exiftool:IPTC:Make}; the template_field is exiftool and the sub-field is IPTC:Make. +(field_arg): optional arguments to pass to the field; for example, with +{folder_album} this is used to pass the path separator used for joining +folders and albums when rendering the field (default is "/" for +{folder_album}). + |filter: You may optionally append one or more filter commands to the end of the template field using the vertical pipe ('|') symbol. Filters may be combined, separated by '|' as in: {keyword|capitalize|parens}. @@ -1456,6 +1469,32 @@ Valid filters are: • function: Run custom python function to filter value; use in format 'function:/path/to/file.py::function_name'. See example at https://github.c om/RhetTbull/osxphotos/blob/master/examples/template_filter.py + • split(x): Split value into a list of values using x as delimiter, e.g. + 'value1;value2' => ['value1', 'value2'] if used with split(;). + • autosplit: Automatically split delimited string into separate values; will + split strings delimited by comma, semicolon, or space, e.g. 'value1,value2' + => ['value1', 'value2']. + • chop(x): Remove x characters off the end of value, e.g. chop(1): 'Value' => + 'Valu'; when applied to a list, chops characters from each list value, e.g. + chop(1): ['travel', 'beach']=> ['trave', 'beac']. + • chomp(x): Remove x characters from the beginning of value, e.g. chomp(1): + ['Value'] => ['alue']; when applied to a list, removes characters from each + list value, e.g. chomp(1): ['travel', 'beach']=> ['ravel', 'each']. + • sort: Sort list of values, e.g. ['c', 'b', 'a'] => ['a', 'b', 'c']. + • rsort: Sort list of values in reverse order, e.g. ['a', 'b', 'c'] => ['c', + 'b', 'a']. + • reverse: Reverse order of values, e.g. ['a', 'b', 'c'] => ['c', 'b', 'a']. + • uniq: Remove duplicate values, e.g. ['a', 'b', 'c', 'b', 'a'] => ['a', 'b', + 'c']. + • join(x): Join list of values with delimiter x, e.g. join(:): ['a', 'b', + 'c'] => 'a:b:c'; the DELIM option functions similar to join(x) but with + DELIM, the join happens before being passed to any filters. + • append(x): Append x to list of values, e.g. append(d): ['a', 'b', 'c'] => + ['a', 'b', 'c', 'd']. + • prepend(x): Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c'] + => ['d', 'a', 'b', 'c']. + • remove(x): Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] => + ['a', 'c']. e.g. if Photo keywords are ["FOO","bar"]: @@ -1468,9 +1507,6 @@ e.g. if Photo description is "my description": • "{descr|titlecase}" renders to: "My Description" -(path_sep): optional path separator to use when joining path-like fields, for -example {folder_album}. Default is "/". - e.g. If Photo is in Album1 in Folder1: • "{folder_album}" renders to ["Folder1/Album1"] @@ -1540,7 +1576,7 @@ This renames any photo that is a favorite as 'Favorite-ImageName.jpg' (where the unmodified original name. ?bool_value: Template fields may be evaluated as boolean (True/False) by -appending "?" after the field name (and following "(path_sep)" or +appending "?" after the field name (and following "(field_arg)" or "[find/replace]". If a field is True (e.g. photo is HDR and field is "{hdr}") or has any value, the value following the "?" will be used to render the template instead of the actual field value. If the template field evaluates @@ -1590,6 +1626,34 @@ If you want to include "{" or "}" in the output, use "{openbrace}" or e.g. "{created.year}/{openbrace}{title}{closebrace}" would result in "2020/{Photo Title}". +Variables + +You can define variables for later use in the template string using the format +{var:NAME,VALUE}. Variables may then be referenced using the format %NAME. +For example: {var:foo,bar} defines the variable %foo to have value bar. This +can be useful if you want to re-use a complex template value in multiple +places within your template string or for allowing the use of characters that +would otherwise be prohibited in a template string. For example, the "pipe" +(|) character is not allowed in a find/replace pair but you can get around +this limitation like so: {var:pipe,{pipe}}{title[-,%pipe]} which replaces the +- character with | (the value of %pipe). + +Variables can also be referenced as fields in the template string, for +example: {var:year,created.year}{original_name}-{%year}. In some cases, use of +variables can make your template string more readable. Variables can be used +as template fields, as values for filters, as values for conditional +operations, or as default values. When used as a conditional value or default +value, variables should be treated like any other field and enclosed in braces +as conditional and default values are evaluated as template strings. For +example: {var:name,Katie}{person contains {%name}?{%name},Not-{%name}}. + +If you need to use a % (percent sign character), you can escape the percent +sign by using %%. You can also use the {percent} template field where a +template field is required. For example: + +{title[:,%%]} replaces the : with % and {title contains +Foo?{title}{percent},{title}} adds % to the title if it contains Foo. + With the --directory and --filename options you may specify a template for the export directory or filename, respectively. The directory will be appended to the export path specified in the export DEST argument to export. For example, @@ -1805,16 +1869,18 @@ Substitution Description directory "{folder_album}" --filename "{album_seq}_{original_name}"'. To start counting at a value other than 0, append - append a period and the starting value to - the field name. For example, to start - counting at 1 instead of 0: '{album_seq.1}'. - May be formatted using a python string - format code. For example, to format as a - 5-digit integer and pad with zeros, use - '{album_seq:05d}' which results in 00000, - 00001, 00002...etc. This may result in - incorrect sequences if you have duplicate - albums with the same name; see also + append '(starting_value)' to the field name. + For example, to start counting at 1 instead + of 0: '{album_seq(1)}'. May be formatted + using a python string format code. For + example, to format as a 5-digit integer and + pad with zeros, use '{album_seq:05d}' which + results in 00000, 00001, 00002...etc. To + format while also using a starting value: + '{album_seq:05d(1)}' which results in 0001, + 00002...etc.This may result in incorrect + sequences if you have duplicate albums with + the same name; see also '{folder_album_seq}'. {folder_album_seq} An integer, starting at 0, indicating the photo's index (sequence) in the containing @@ -1825,17 +1891,20 @@ Substitution Description directory "{folder_album}" --filename "{folder_album_seq}_{original_name}"'. To start counting at a value other than 0, - append append a period and the starting - value to the field name. For example, to - start counting at 1 instead of 0: - '{folder_album_seq.1}' May be formatted - using a python string format code. For - example, to format as a 5-digit integer and - pad with zeros, use '{folder_album_seq:05d}' - which results in 00000, 00001, 00002...etc. - This may result in incorrect sequences if - you have duplicate albums with the same name - in the same folder; see also '{album_seq}'. + append '(starting_value)' to the field name. + For example, to start counting at 1 instead + of 0: '{folder_album_seq(1)}' May be + formatted using a python string format code. + For example, to format as a 5-digit integer + and pad with zeros, use + '{folder_album_seq:05d}' which results in + 00000, 00001, 00002...etc. To format while + also using a starting value: + '{folder_album_seq:05d(1)}' which results in + 0001, 00002...etc.This may result in + incorrect sequences if you have duplicate + albums with the same name in the same + folder; see also '{album_seq}'. {comma} A comma: ',' {semicolon} A semicolon: ';' {questionmark} A question mark: '?' @@ -1850,7 +1919,7 @@ Substitution Description {lf} A line feed: '\n', alias for {newline} {cr} A carriage return: '\r' {crlf} a carriage return + line feed: '\r\n' -{osxphotos_version} The osxphotos version, e.g. '0.49.9' +{osxphotos_version} The osxphotos version, e.g. '0.50.0' {osxphotos_cmd_line} The full command line used to run osxphotos The following substitutions may result in multiple values. Thus if specified @@ -1941,6 +2010,14 @@ Substitution Description {strip} Use in form '{strip,TEMPLATE}'; strips whitespace from begining and end of rendered TEMPLATE value(s). +{format} Use in form, '{format:TYPE:FORMAT,TEMPLATE}'; + converts TEMPLATE value to TYPE then formats the + value using Python string formatting codes + specified by FORMAT; TYPE is one of: 'int', + 'float', or 'str'. For example, + '{format:float:.1f,{exiftool:EXIF:FocalLength}}' + will format focal length to 1 decimal place (e.g. + '100.0'). {function} Execute a python function from an external file and use return value as template substitution. Use in format: {function:file.py::function_name} where @@ -3812,7 +3889,7 @@ In its simplest form, a template statement has the form: `"{template_field}"`, f Template statements may contain one or more modifiers. The full syntax is: -`"pretext{delim+template_field:subfield|filter(path_sep)[find,replace] conditional?bool_value,default}posttext"` +`"pretext{delim+template_field:subfield(field_arg)|filter[find,replace] conditional?bool_value,default}posttext"` Template statements are white-space sensitive meaning that white space (spaces, tabs) changes the meaning of the template statement. @@ -3833,6 +3910,8 @@ e.g. if Photo keywords are `["foo","bar"]`: `:subfield`: Some templates have sub-fields, For example, `{exiftool:IPTC:Make}`; the template_field is `exiftool` and the sub-field is `IPTC:Make`. +`(field_arg)`: optional arguments to pass to the field; for example, with `{folder_album}` this is used to pass the path separator used for joining folders and albums when rendering the field (default is "/" for `{folder_album}`). + `|filter`: You may optionally append one or more filter commands to the end of the template field using the vertical pipe ('|') symbol. Filters may be combined, separated by '|' as in: `{keyword|capitalize|parens}`. Valid filters are: @@ -3847,6 +3926,18 @@ Valid filters are: - `brackets`: Enclose value in brackets, e.g. 'value' => '[value]' - `shell_quote`: Quotes the value for safe usage in the shell, e.g. My file.jpeg => 'My file.jpeg'; only adds quotes if needed. - `function`: Run custom python function to filter value; use in format 'function:/path/to/file.py::function_name'. See example at https://github.com/RhetTbull/osxphotos/blob/master/examples/template_filter.py +- `split(x)`: Split value into a list of values using x as delimiter, e.g. 'value1;value2' => ['value1', 'value2'] if used with split(;). +- `autosplit`: Automatically split delimited string into separate values; will split strings delimited by comma, semicolon, or space, e.g. 'value1,value2' => ['value1', 'value2']. +- `chop(x)`: Remove x characters off the end of value, e.g. chop(1): 'Value' => 'Valu'; when applied to a list, chops characters from each list value, e.g. chop(1): ['travel', 'beach']=> ['trave', 'beac']. +- `chomp(x)`: Remove x characters from the beginning of value, e.g. chomp(1): ['Value'] => ['alue']; when applied to a list, removes characters from each list value, e.g. chomp(1): ['travel', 'beach']=> ['ravel', 'each']. +- `sort`: Sort list of values, e.g. ['c', 'b', 'a'] => ['a', 'b', 'c']. +- `rsort`: Sort list of values in reverse order, e.g. ['a', 'b', 'c'] => ['c', 'b', 'a']. +- `reverse`: Reverse order of values, e.g. ['a', 'b', 'c'] => ['c', 'b', 'a']. +- `uniq`: Remove duplicate values, e.g. ['a', 'b', 'c', 'b', 'a'] => ['a', 'b', 'c']. +- `join(x)`: Join list of values with delimiter x, e.g. join(:): ['a', 'b', 'c'] => 'a:b:c'; the DELIM option functions similar to join(x) but with DELIM, the join happens before being passed to any filters. +- `append(x)`: Append x to list of values, e.g. append(d): ['a', 'b', 'c'] => ['a', 'b', 'c', 'd']. +- `prepend(x)`: Prepend x to list of values, e.g. prepend(d): ['a', 'b', 'c'] => ['d', 'a', 'b', 'c']. +- `remove(x)`: Remove x from list of values, e.g. remove(b): ['a', 'b', 'c'] => ['a', 'c']. e.g. if Photo keywords are `["FOO","bar"]`: @@ -3859,8 +3950,6 @@ e.g. if Photo description is "my description": - `"{descr|titlecase}"` renders to: `"My Description"` -`(path_sep)`: optional path separator to use when joining path-like fields, for example `{folder_album}`. Default is "/". - e.g. If Photo is in `Album1` in `Folder1`: - `"{folder_album}"` renders to `["Folder1/Album1"]` @@ -3903,7 +3992,7 @@ This can be used to rename files as well, for example: This renames any photo that is a favorite as 'Favorite-ImageName.jpg' (where 'ImageName.jpg' is the original name of the photo) and all other photos with the unmodified original name. -`?bool_value`: Template fields may be evaluated as boolean (True/False) by appending "?" after the field name (and following "(path_sep)" or "[find/replace]". If a field is True (e.g. photo is HDR and field is `"{hdr}"`) or has any value, the value following the "?" will be used to render the template instead of the actual field value. If the template field evaluates to False (e.g. in above example, photo is not HDR) or has no value (e.g. photo has no title and field is `"{title}"`) then the default value following a "," will be used. +`?bool_value`: Template fields may be evaluated as boolean (True/False) by appending "?" after the field name (and following "(field_arg)" or "[find/replace]". If a field is True (e.g. photo is HDR and field is `"{hdr}"`) or has any value, the value following the "?" will be used to render the template instead of the actual field value. If the template field evaluates to False (e.g. in above example, photo is not HDR) or has no value (e.g. photo has no title and field is `"{title}"`) then the default value following a "," will be used. e.g. if photo is an HDR image, @@ -3934,6 +4023,15 @@ If you want to include "{" or "}" in the output, use "{openbrace}" or "{closebra e.g. `"{created.year}/{openbrace}{title}{closebrace}"` would result in `"2020/{Photo Title}"`. +**Variables** + +You can define variables for later use in the template string using the format `{var:NAME,VALUE}`. Variables may then be referenced using the format `%NAME`. For example: `{var:foo,bar}` defines the variable `%foo` to have value `bar`. This can be useful if you want to re-use a complex template value in multiple places within your template string or for allowing the use of characters that would otherwise be prohibited in a template string. For example, the "pipe" (`|`) character is not allowed in a find/replace pair but you can get around this limitation like so: `{var:pipe,{pipe}}{title[-,%pipe]}` which replaces the `-` character with `|` (the value of `%pipe`). + +Variables can also be referenced as fields in the template string, for example: `{var:year,created.year}{original_name}-{%year}`. In some cases, use of variables can make your template string more readable. Variables can be used as template fields, as values for filters, as values for conditional operations, or as default values. When used as a conditional value or default value, variables should be treated like any other field and enclosed in braces as conditional and default values are evaluated as template strings. For example: `{var:name,Katie}{person contains {%name}?{%name},Not-{%name}}`. + +If you need to use a `%` (percent sign character), you can escape the percent sign by using `%%`. You can also use the `{percent}` template field where a template field is required. For example: + +`{title[:,%%]}` replaces the `:` with `%` and `{title contains Foo?{title}{percent},{title}}` adds `%` to the title if it contains `Foo`. The following template field substitutions are availabe for use the templating system. @@ -4010,8 +4108,8 @@ The following template field substitutions are availabe for use the templating s |{moment}|The moment title of the photo| |{uuid}|Photo's internal universally unique identifier (UUID) for the photo, a 36-character string unique to the photo, e.g. '128FB4C6-0B16-4E7D-9108-FB2E90DA1546'| |{id}|A unique number for the photo based on its primary key in the Photos database. A sequential integer, e.g. 1, 2, 3...etc. Each asset associated with a photo (e.g. an image and Live Photo preview) will share the same id. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{id:05d}' which results in 00001, 00002, 00003...etc. | -|{album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album. Only valid when used in a '--filename' template and only when '{album}' or '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{album_seq}_{original_name}"'. To start counting at a value other than 0, append append a period and the starting value to the field name. For example, to start counting at 1 instead of 0: '{album_seq.1}'. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{album_seq:05d}' which results in 00000, 00001, 00002...etc. This may result in incorrect sequences if you have duplicate albums with the same name; see also '{folder_album_seq}'.| -|{folder_album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album and folder path. Only valid when used in a '--filename' template and only when '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{folder_album_seq}_{original_name}"'. To start counting at a value other than 0, append append a period and the starting value to the field name. For example, to start counting at 1 instead of 0: '{folder_album_seq.1}' May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{folder_album_seq:05d}' which results in 00000, 00001, 00002...etc. This may result in incorrect sequences if you have duplicate albums with the same name in the same folder; see also '{album_seq}'.| +|{album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album. Only valid when used in a '--filename' template and only when '{album}' or '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{album_seq}_{original_name}"'. To start counting at a value other than 0, append append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{album_seq(1)}'. May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name; see also '{folder_album_seq}'.| +|{folder_album_seq}|An integer, starting at 0, indicating the photo's index (sequence) in the containing album and folder path. Only valid when used in a '--filename' template and only when '{folder_album}' is used in the '--directory' template. For example '--directory "{folder_album}" --filename "{folder_album_seq}_{original_name}"'. To start counting at a value other than 0, append '(starting_value)' to the field name. For example, to start counting at 1 instead of 0: '{folder_album_seq(1)}' May be formatted using a python string format code. For example, to format as a 5-digit integer and pad with zeros, use '{folder_album_seq:05d}' which results in 00000, 00001, 00002...etc. To format while also using a starting value: '{folder_album_seq:05d(1)}' which results in 0001, 00002...etc.This may result in incorrect sequences if you have duplicate albums with the same name in the same folder; see also '{album_seq}'. | |{comma}|A comma: ','| |{semicolon}|A semicolon: ';'| |{questionmark}|A question mark: '?'| @@ -4026,7 +4124,7 @@ The following template field substitutions are availabe for use the templating s |{lf}|A line feed: '\n', alias for {newline}| |{cr}|A carriage return: '\r'| |{crlf}|a carriage return + line feed: '\r\n'| -|{osxphotos_version}|The osxphotos version, e.g. '0.49.9'| +|{osxphotos_version}|The osxphotos version, e.g. '0.50.0'| |{osxphotos_cmd_line}|The full command line used to run osxphotos| |{album}|Album(s) photo is contained in| |{folder_album}|Folder path + album photo is contained in. e.g. 'Folder/Subfolder/Album' or just 'Album' if no enclosing folder| @@ -4047,6 +4145,7 @@ The following template field substitutions are availabe for use the templating s |{detected_text}|List of text strings found in the image after performing text detection. Using '{detected_text}' will cause osxphotos to perform text detection on your photos using the built-in macOS text detection algorithms which will slow down your export. The results for each photo will be cached in the export database so that future exports with '--update' do not need to reprocess each photo. You may pass a confidence threshold value between 0.0 and 1.0 after a colon as in '{detected_text:0.5}'; The default confidence threshold is 0.75. '{detected_text}' works only on macOS Catalina (10.15) or later. Note: this feature is not the same thing as Live Text in macOS Monterey, which osxphotos does not yet support.| |{shell_quote}|Use in form '{shell_quote,TEMPLATE}'; quotes the rendered TEMPLATE value(s) for safe usage in the shell, e.g. My file.jpeg => 'My file.jpeg'; only adds quotes if needed.| |{strip}|Use in form '{strip,TEMPLATE}'; strips whitespace from begining and end of rendered TEMPLATE value(s).| +|{format}|Use in form, '{format:TYPE:FORMAT,TEMPLATE}'; converts TEMPLATE value to TYPE then formats the value using Python string formatting codes specified by FORMAT; TYPE is one of: 'int', 'float', or 'str'. For example, '{format:float:.1f,{exiftool:EXIF:FocalLength}}' will format focal length to 1 decimal place (e.g. '100.0'). | |{function}|Execute a python function from an external file and use return value as template substitution. Use in format: {function:file.py::function_name} where 'file.py' is the name of the python file and 'function_name' is the name of the function to call. The function will be passed the PhotoInfo object for the photo. See https://github.com/RhetTbull/osxphotos/blob/master/examples/template_function.py for an example of how to implement a template function.| diff --git a/docs/.buildinfo b/docs/.buildinfo index 1b20aacb..1cf73e57 100644 --- a/docs/.buildinfo +++ b/docs/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 840166640a0eca4a34f53df341c84489 +config: 2319c5f6348daed917bcf14a84e56927 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_modules/index.html b/docs/_modules/index.html index 8682046d..101a96bd 100644 --- a/docs/_modules/index.html +++ b/docs/_modules/index.html @@ -5,7 +5,7 @@ -