Installation
August 6, 2024 ยท View on GitHub
Template pattern consist of a raw text interleaved with tag invocations:
Raw text with a %TagCategory.TagName() in it
Raw text is treated as a constant - it doesn't change across template evaluations.
Tag invocation starts with % symbol followed by the tag name, argument list and (optionally) its context.
Tag name
A fully qualified tag name consists of a category and tag name separated by a single dot ..
The tag name is case-sensitive and conforms to CamelCase naming convention.
The category name is case-insensitive but to keep convention consistent it is also presented in the same (CamelCase) manner.
If the tag name is unique across categories it can be used without explicit category specification (and separating dot) like this:
Raw text with a %UniqueTag() in it
When non-unique tag name (present in more than one category) is used this way, tempren will report an error about tag ambiguity.
Tag configuration arguments
Some tags might or have to be configured before they can do their work. To do so, the user must pass configuration arguments in the tag argument list. What arguments are expected and in what order can be found by looking at tag signature in the built-in tag documentation.
The argument list follows tag name and is contained between parentheses: ().
Each argument value is separated by a single coma , (with optional white spaces) and can be one of three types:
intfor integer numbers (that match-?[0-9]+regex)strfor quoted string literals (both single'and double"quotation marks can be used)boolfor boolean flags
Numbers can be accepted only in decimal (base 10) representation without fractional part: %Count(0, 1, 4)
String literals may contain any character except for the used quote mark - if the quote mark needs to be passed,
it should be escaped (prefixed) with a single backslash character, i.e. \' or \".
Boolean flags can accept two types of values: True/true or False/false.
Additionally, a shortcut exists for setting the flag argument to True - just use the flag name as an argument value (similar to explicit argument names in programming languages).
Therefore, the following invocations are equivalent:
%Trim(-2, left=True)
%Trim(-2, true)
%Trim(-2, left)
The tag prototype (which can be found in tag build-in documentation) describes the names and types of every argument the tag configuration expects:
%Trim(width: int, left: bool = False, right: bool = False){...}
The above prototype indicates that this tag accepts up to 3 arguments named width, left and right. The last two are optional as they have default False value.
User can prefix argument value with its name and = symbol to explicitly specify values just for the named arguments: %Trim(-2, right=True). This way, arguments can be passed out of (defined in the prototype) order: %Trim(left, width=-1)
Order of arguments is important if explicit names are not used: %Trim(-1, True) will set left flag because it's second in the argument list.
Context
Similar to arguments, some tags can (or have to) operate on the context which is another way to pass the data to the tag. In contrast to the arguments, which have to stay the same during the entire renaming operation, contexts can change between each tag invocation. They might be considered a dynamic argument.
To pass a context to the tag invocation, use curly braces {} with template expression embedded between.
The curly braces can be placed directly after the argument list:
%Trim(5, left){Long text}
or (if the argument list is empty) directly after the tag name:
%Upper{small text}
The most important feature of contexts is their dynamic nature - they can contain entire sub-templates.
In the following example, the Lower tag receives context containing the processed file extension and makes it lowercase:
%Lower(){%Ext()}
To check if the tag might operate on a context, check build-in documentation. The symbol after the tag name indicates context requirements:
- No symbol - when prototype ends with just argument list (
(...)) - indicates that the tag doesn't operate on contexts and passing one will result in an error. {...}symbol indicates that this tag requires some context to be passed[{...}]symbol denotes that the tag can use the context if one is passed to it
Pipe list sugar
Note: Currently pipe list syntax is limited as it has to be the last element of the whole (sub)template. This might change in the future.
Sometimes it is desirable to create a chain of context invocations such as:
%Lower{%Collapse{%Strip{%Name()}}}
To streamline such operations, pipe list syntax sugar can be used and above expression can be written as:
%Name()|%Strip()|%Collapse()|%Lower()
In the pipe list, there can be no contexts (therefore no curly braces) as the context is passed directly from the previous tag - from left to right.
Note: For pipe list syntax, an empty argument list is required to denote the end of the tag name. This behaviour might change in the future.
Filtering
Filtering allows for inclusion/exclusion of specific files from the renaming operation.
There are three types of filtering expressions supported:
template- tag-template evaluated Python predicate expression, e.g.:%Size() > 10*1024glob- globbing expression, e.g.:*.mp3,IMG_????.jpgregex- python-flavored regular expressions, e.g.:.*\.jpe?g
Template-based filtering
Template-based filtering is the most powerful and allows for the inclusion/exclusion of files based on their metadata.
A filter expression can be passed with --filter-template/-ft flag.
Filter expression tag template is rendered for each file and evaluated as Python expression.
If the result of evaluation is truthy, the file is considered for renaming.
For example, the following filtering template will exclude files larger than 1024 bytes:
%Size() <= 1024
Standard Python boolean operators (and, or, not) and built-in functions can be used to chain multiple conditions.
For example, to include only image files that are not PNGs, the following filter expression can be used:
%IsMime("image") and not %Ext().endswith("png")
Note: Filtering templates are evaluated a bit differently from the ones used for name generation - values generated from the tags are escaped to create valid Python literals. Therefore, above expression could be rendered as:
True and not ".png".endswith("png")
Glob filtering
Glob filtering allows to include/exclude files based on the glob expression matching their filenames. People used to the terminal should be familiar with this kind of filtering as it's the same one used by most *nix shells.
For example, to rename only files with an Image_ as a prefix, the following pattern can be used:
Image_*
Regex filtering
Regular expression filtering allows to include/exclude files based on regex expression matching their filenames.
For example, to rename only files that start with a digit, following pattern can be used:
^\d.*
This feature uses Python-flavored regular expressions.
Note: Regular expressions are infamous for their complexity. It is always better to prefer a simpler solution if it can accomplish the same result.
Filter inversion
Sometimes it might be easier to specify a filter for files which should not be included.
To negate/invert any filtering expression you can use --filter-invert/-fi flag.
Template-based sorting
In some cases (i.e. when Count tag is used), files should be processed in specific order to make renaming useful.
--sort/-s flag can be used to order files based on their metadata.
Sort expression is similar to the filter template in a way that it is also used to generate a Python expression which, after evaluation, is used to order the files considered for renaming.
For example, to order files based on their original name, the following expression can be used:
%Name()
In contrast to filtering expressions, the sorting expression has to be evaluated into a valid Python tuple literal (excluding parenthesis). So, to add another sorting criteria (for cases where the first key may repeat across files), a comma , should be used as a sorting criteria separator.
For example, to order files based on their extension the first and then their size, the following expression can be used:
%Ext(), %Size()
Note: Sorting templates are evaluated a bit differently from the ones used for name generation - values generated from the tags are escaped to create valid Python literals. Therefore, above expression could be rendered as:
(".png", 12345)
Sorting order inversion
By default, the sorting expression order files in ascending order.
To change this behaviour, --sort-invert/-si flag can be used.
Conflict resolution strategies
File conflict arises when a template generates the same path for two different files or the generated path already exists in the filesystem.
tempren supports the following conflict resolution strategies:
stop- Reports an error and stops program execution (default, indicated by--conflict-stop/-csflag)ignore- Reports problem as a warning and continues renaming leaving source file name intact (enabled with--conflict-ignore/-ciflag)override- Replaces destination file with the one being processed (enabled with--conflict-override/-coflag)manual- Interactively prompts the user to select one of the above conflict resolutions (enabled with--conflict-manual/-cmflag)
Ad-hoc tags
If the built-in tag library doesn't contain the tag appropriate for the user problem, tempren allows importing external executables as new, ad-hoc tags.
To create an ad-hoc tag, you will need to provide an executable path as an argument to the --ad-hoc/-ah flag. After doing so, a new tag will be placed under Adhoc category, and you will be able to see its documentation (i.e. invocation details) with the help of --help/-h flag:
tempren --ad-hoc awk --help awk
Note: When executing the ad-hoc tags, even with
--dry-run/-drflag,temprendoesn't have control of the behaviour of the invoked executables. Care should be taken to make sure that the user-provided program doesn't create any undesirable side effects upon template execution.
There are two ways in which an executable associated with an ad-hoc tag can be invoked. If no context is provided in the tag template, the relative path to the processed file is appended as the last parameter to the command line.
For example, to count lines of the processed text file, an awk utility can be used as such:
tempren --ad-hoc Awk=awk '%Base()_%Awk("END {print NR}")%Ext()' *.txt
This invocation will result in the execution of awk 'END {print NR}' <processed-file-path> command for each processed file.
Explicit naming (Awk= part in the above example) can be skipped. This will result in the base name of the executable being used as a tag name.
If the context is provided, it will be passed to the command's standard input (stdin) and the command will not receive the processed file path.
For example, tr utility can be used to remove some characters from the base file name by passing it to its standard input (context) as such:
tempren --ad-hoc Tr=tr '%Tr(" _\\-.@~", "-"){%Base()}%Ext()' --help Tr
Regardless of how the underlying ad-hoc executable will be invoked, any data sent to the stdout by it will be used as a tag output
and any data sent to the stderr channel will be ignored.
If the invoked command returns a non-zero error code, tempren will report this as an error.
Program arguments can be passed in the ad-hoc tag arguments but care should be taken to
separate them correctly as spaces do not delimit the arguments like in the shell environment.
For example, to pass two parameters to the ad-hoc Program, the following syntax should be used:
%Program("--flag", "flag-argument")
Tag aliases
Tag aliases are templates that can be reused as standalone tags.
To create a new alias, --alias/-a flag can be used:
tempren --alias 'Normalized=%Lower{%Name()}' --help Normalized
Tags created from the aliases cannot receive any arguments or context - they are simply placeholders where the underlying template will be inserted.
Various options
Dry run
To facilitate discovery-based usage learning, tempren's --dry-run/-dr flag can be used to disable the actual file renaming stage of the pipeline. This way, users can test their templates without making changes to the filesystem.
Note: While dry-run is active, side effects from filtering/sorting template expressions (which are valid Python code), ad-hoc tags or even tags themselves may still affect the file system.
Be careful not to copy-paste templates that look suspicious.
Verbosity levels
The number of messages produced by the tool can be increased with --verbose/-v flag
and decreased by --quiet/-q flag.
Normal messages are directed to the standard output (stdout) while warnings and errors are sent to stderr.
Hidden files handling
By default, tempren won't consider hidden files or directories for renaming.
To include such files in the renaming process, --include-hidden/-ih flag can be used.
Note:
--include-hiddenin combination with--recursiveflag, changes how file discovery is performed. When both flags are specified, hidden directories and any files in them will be considered for renaming.
Loading arguments from files
If the command line argument starts with a @ symbol, tempren will assume that it is a file containing the desired program arguments, and it will load it (treating each line as a separate argument).
This is especially useful in the case of reusing the same pattern (or program arguments in general) over and over.