{ "info": { "author": "SiriusStarr", "author_email": "2049163+SiriusStarr@users.noreply.github.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Topic :: Utilities" ], "description": "# autotagical\n\n*autotagical* is a utility to automagically rename and sort tagged files (such\nas those produced by [TagSpaces](https://github.com/tagspaces/tagspaces))\naccording to user-defined schemas. It reads in tagged files from one of more\ninput directories then renames and/or moves them to an output folder hierarchy\naccording to rules specified in user-provided schemas. It is intended for use\nin concert with file tagging software, e.g.\n[TagSpaces](https://github.com/tagspaces/tagspaces).\n\n## Getting Started/Installation\n\n*autotagical* may be most easily installed with *pip* by running:\n\n```bash\npip install autotagical\n```\n\nIf you'd like to run *autotagical* by cloning this repository, then you'll need\nto install the following requirements, e.g. with *pip*:\n\n* `setuptools`\n* `jsonschema>=3`\n* `packaging`\n\n## Using autotagical\n\n### Usage\n\n```bash\nautotagical [-h] [-V] [-C ] [-H] [-i ]\n [-I ] [-R] [-o ] [-O]\n [-g ] [-s ] [-A] [--cleanin]\n [--cleanout] [-c] [-F] [-k] [-m] [-M] [-n] [-N] [-t]\n [--debug] [-l ] [-L] [-P] [-q] [-v] [--force]\n [--yes]\n```\n\n### Help Options\n\nThese options display helpful information and exit.\n\n* `[-h/--help]` -- Display a help/usage message and exit.\n* `[-V/--version]` -- Display the current version and information about known\n file formats and exit.\n\n### Configuration Options\n\n* `[-C/--config ]` -- Loads the config file at the specified path.\n\n### Input Options\n\nThese options determine behavior loading in files to be moved and/or renamed.\nAt least one input folder must be specified.\n\n* `[-H/--hidden]` -- Process hidden files (and directories, if -R is specified).\n* `[-i/--input ]` -- Path to a folder with input files. May be\n specified more than once.\n* `[-I/--ignore ]` -- Path to file patterns (regex format) to\n ignore (each on new line). May be specified more than once.\n* `[-R/--recursive]` -- Load files recursively from input folders, i.e. descend\n into subfolders.\n\n### Output Options\n\nThese options determine behavior in outputting move/renamed files (but do not\nspecify the rules by which they are to be moved and/or renamed). At least one\noutput folder must be specified (by one option or the other).\n\n* `[-o/--output]` -- Path to a root folder to output files to. May be specified\n more than once (output will be duplicated to each).\n* `[-O/--organize]` -- Organize files in place (i.e. use the first input folder\n for output). Often used with -R.\n\n### Schema Options\nThese options specify the rules for moving/renaming files and are the heart of\n*autotagical*. Information on the structure of these files may be found below\nin the [Tag Group Format](#tag-group-format) and\n[Schema Format](#schema-format) sections.\n\n* `[-g/--groups ]` -- Path to a file to read tag groups from.\n May be specified more than once (groups will be combined). Files may be in\n either the *[TagSpaces](https://github.com/tagspaces/tagspaces)* or the\n *autotagical* format.\n* `[-s/--schema ]` -- Path to a schema file to move/rename files\n based on. May be specified more than once, in which case rules are\n prioritized in the order files are specified.\n\n### Functionality Options\n\nThese options tweak the default functioning of *autotagical* as specified\nbelow, typically adjusting how various circumstances are dealt with.\n\n* `[-A/--allmatchroot]` -- Makes the root of an output folder match all tags,\n i.e. every single file will be moved to the output folder, even if it does not\n match anywhere more specifically. Use of this option is bad practice\n (consider using the `/*|` operator as a root filter instead), but it is\n provided for the user's convenience. This option does **not** imply `-M`,\n i.e. files that could not be renamed will not be moved to the root folder\n just because `-A` is set.\n* `[--cleanin]` -- Clean up (delete) all empty folders in the input folder/s.\n This *will* recurse, whether or not the `-R` flag is set.\n* `[--cleanout]` -- Clean up (delete) all empty folders in the output folder.\n This *will* recurse, whether or not the `-R` flag is set.\n* `[-c/--clean]` -- Clean up (delete) all empty folders in both input and output\n folders.\n* `[-F/--failforcerename]` -- This option flags failing to rename a\n manually-named file that is being forcibly renamed due to the `-N` option\n should be considered a failure to name the file. That sounds complicated, but\n consider these cases:\n * `[-F]` -- Normal behavior (option will be ignored).\n * `[-N]` -- Force rename manually-named files, but manual names are \"good\n enough\" and manually-named files that cannot be renamed will be moved.\n * `[-F -N]` -- Force rename manually-named files and treat failures as\n failures. Manually-named files that cannot be renamed will **not** be moved.\n * `[-N -M]` -- Force rename manually-named files. All files will be moved.\n * `[-F -N -M]` -- Equivalent to `-N -M`. `-F` has no effect.\n* `[-k/--keep]` -- Keep original files in the input folders untouched, i.e copy\n files to their new destinations rather than move them.\n* `[-m/--move]` -- Only move files into a directory structure, do not try to\n rename them.\n* `[-M/--moveall]` -- Move all files, not only ones that are manually-named/\n successfully renamed.\n* `[-n/--name]` -- Only rename files, do not try to move them into any directory\n structure. All files will be placed in the root of the output folder.\n* `[-N/--renamemanual]` -- Forcibly try to rename manually-named files, not just\n unnamed ones.\n* `[-t/--trial]` -- Trial run. Do not actually move or rename files, just log\n what would happen. Combine with `-v` to check output before live run.\n **Using this is good practice,** especially after making any changes to a\n schema or options. The `-t` option ensures no changes will be reflected to\n disk whatsoever.\n\n### Logging Options\n\nThese options tweak what sorts of messages are displayed when *autotagical* is\nrun (and whether to save them or just print them to the console).\n\n* `[--debug]` -- Display absolutely everything. You should probably never use\n this.\n* `[-l/--log ]` -- Output messages to the specified file rather than\n just the console. By default, messages will be appended to the end of the\n file.\n* `[-L/--overwritelog]` -- Overwrite the specified log file, rather than append\n to it. Has no effect without `-l`.\n* `[-P/--posix]` -- Silence warnings specific to Windows. Use this **only** if\n the files are never to be used with Windows systems (which are pickier about\n what file names can contain).\n* `[-q/--quiet]` -- Silence all warnings and only display actual errors. Use of\n this is **not recommended,** as warnings are typically printed for good\n reason.\n* `[-v/--verbose]` -- Print all actions taken. This will list every file\n movement/renaming, rather than merely warning about failures. Most useful\n when combined with `-t` to check that a schema is doing what one wants before\n running it for real.\n\n### Unsafe Options\n\nDo not use these unless you have very good reason to. **Data loss can occur.**\n\n* `[--force]` -- Forcibly move/rename files, even if there is a file or\n directory in the way. **This will clobber files;** use at your own risk, as\n data loss can occur.\n* `[--yes]` -- Assume \"yes\" for all user prompts. This implies `--force` and\n **will clobber files and directories.** Use at your own risk, as data loss\n can occur.\n\n### Setting Priority\n\n*autotagical* will always preferentially use settings specified in the\nfollowing order, from highest to lowest, with each overriding any settings from\nlower priority sources. Note that only **one** config file will be loaded (the\nfirst by priority).\n\n1. Command-line arguments.\n1. Config file (first found from below).\n 1. Config file loaded using `-C/--config` argument.\n 1. `.autotagrc` file in output folder (first folder containing one is used).\n 1. `.autotagrc` file in input folder (first folder containing one is used).\n 1. `.autotagrc` file in `autotagical` module folder.\n\n### Config File Format\n`.autotagrc` (or any config file specified via command-line) should have the\nsame format as any command line arguments one would otherwise care to pass.\n**Unsafe options will be ignored in config files,** i.e. `--force` and `--yes`\nwill have no effect if set in a config file. This is to prevent data loss\nwithout explicit user input. Whitespace and newlines are ignored, e.g. one\nmight write:\n\n```bash\n-H\n\n -P\n```\n\nin a config file to process hidden and ignore Windows-specific warnings.\n\n## Tag Group Format\n\n*autotagical* is capable of reading the JSON files produced by exporting tag\ngroups from [TagSpaces](https://github.com/tagspaces/tagspaces). Alternately,\ntag groups may be defined in a more simple, somewhat more human-readable\nfashion in JSON. This *autotagical* tag group format supports additional\nfeatures not available in the TagSpaces format, detailed below.\n\n```json\n{\n \"file_type\": \"autotagical_tag_groups\",\n \"tag_group_file_version\": \"1.1\",\n \"tag_groups\": [\n {\n \"name\": \"tag group 1\",\n \"tags\": [\"tag1\", \"tag2\"...]\n },\n {\n \"name\": \"tag group 2\",\n \"tags\": [\"tag3\", \"/G|tag group 1\", \"/RE|regex 1\",...]\n },\n ]\n}\n```\n\n### Inheritance\n\nIn the *autotagical* format, tag groups support simple inheritance, where a\nchild tag group may be defined in terms of one or more parent tag groups (as\nwell as any additional tags). Inheritance is indicated by prefixing a group\nname with `/G|` in the `tags` property of a group. In such cases, the child\ngroup will inherit all tags in any of the parent groups. This is useful for\nsimplicity; it ensures that one only has to manually define the most \"leaf\" tag\ngroups while still writing filters based on more broad groups, all of which\nwill update if the more refined groups are updated. Consider the following\nsimple use case:\n\n```json\n{\n \"file_type\": \"autotagical_tag_groups\",\n \"tag_group_file_version\": \"1.1\",\n \"tag_groups\": [\n {\n \"name\": \"American Styles\",\n \"tags\": [\n \"ipa\",\n \"dipa\",\n \"pale_ale\"\n ]\n },\n {\n \"name\": \"Belgian Styles\",\n \"tags\": [\n \"witbier\",\n \"dubbel\",\n \"tripel\"\n ]\n },\n {\n \"name\": \"Beer\",\n \"tags\": [\n \"/G|American Styles\",\n \"/G|Belgian Styles\"\n ]\n }\n ]\n}\n```\n\nHere, we have defined the `Beer` group in terms of `American Styles` and\n`Belgian Styles`, rather than having to specify all 6 tags that should fall\nunder it. Not only is this quicker to write, but it prevents errors of\noversight when one decides to add tags later. If, for example, `quadrupel`\nis added to the `Belgian Styles` group, it will be part of the `Beer` group\nwithout one having to remember to manually add it in two places. While this\nsimple case doesn't seem that unmanageable without inheritance, the number of\nplaces where duplicate tags have to be added can quickly spiral out of control\nwith multiple levels of tag group.\n\nKeep in mind the following details about inheritance:\n* **Multiple inheritance** -- Tag groups can inherit from multiple parent\n group (as shown in the example).\n* **Multilevel inheritance** -- Tag groups support multilevel inheritance,\n i.e. an `Alcohol` group might inherit from `Beer` which inherits from\n `American Styles`.\n* **The (lack of) diamond problem** -- As there is no overriding in tag group\n inheritance, the diamond problem (where a grandparent is inherited via two\n different routes) is handled without problem.\n* **Circular inheritance** -- It is okay for two groups to inherit from each\n other (whether via intermediaries or not). Each inheritance path will\n only be followed once, i.e. a tag group will stop \"following\" an\n inheritance path if it is instructed to inherit from itself.\n* **Flexible ordering** -- Tag group inheritance is flexible in the order that\n groups are defined. There is no need for a tag group to be located after\n a group it inherits from. In fact, tag groups can inherit from groups in\n completely different tag group files, regardless of the order they are loaded\n in (so long as they are both loaded).\n\n### Regex Tag Groups\n\nThe *autotagical* tag group format supports defining tag groups in terms of\nregexes. This can be incredibly powerful in certain situations. For example,\nconsider tagged bank statements. Rather than having to manually add every\naccount number tag to an \"Account Number\" group, one can instead define a tag\ngroup as follows:\n\n```json\n{\n \"name\": \"Account Number\",\n \"tags\": [\"/RE|(?:xx|\\\\*\\\\*)[0-9]{4}\"]\n}\n\n```\n\nThis will make any tag of the form `**1234` or `xx1234` match the \"Account\nNumber\" tag group. If one deals with a large number of tags with a standardized\nform, this can be extremely valuable, especially if they change frequently.\n\nKeep in mind the following details about regex tag groups:\n* **Full match** -- Regexes are used with `re.fullmatch()` and as such must\n match 100% of the tag name.\n* **Inheritance** -- Regexes will be inherited as with any other tags in a\ngroup.\n* **Mixed and matched** -- A tag group can be defined in terms of any\n combination of inheritance, normal tags, or regexes. They do not need to be\n specified solely in terms of regexes.\n* **Tag in group (/?TIG|) operator** -- Regex tag groups work normally with\n the tag in group format string operator. The first tag to match the regex\n will be returned for it.\n\n## Schema Format\n\nA schema is defined in a human-readable fashion in JSON and should consist of a\nsingle object as follows:\n\n```json\n{\n \"file_type\": \"autotagical_schema\",\n \"schema_file_version\": \"1.1\",\n \"tag_formats\": [],\n \"unnamed_patterns\": [],\n \"renaming_schemas\": [],\n \"movement_schema\": []\n}\n```\n\nEach of these four keys should be assigned to an array, the structure of which\nis described in the following sections.\n\n### tag_formats\n\n```json\n\"tag_formats\": [\n {\n \"tag_pattern\": \"Regex containing groups: file, raw_tags, tags, and extension.\",\n \"tag_split_pattern\": \"Regex to split tags with\"\n },\n ...\n]\n\n```\n\nThe various patterns must be valid Python regexes. \"tag_pattern\" will be used\nwith `re.fullmatch()` and should match the entirety of a file name and contain\nthe following named groups:\n\n* `file` -- Matches the original file name (without tags and extension).\n* `raw_tags` -- Matches the entirety of tag data to be preserved, including any\ndelimeters/demarcating characters.\n* `tags` -- Matches only the tags themselves and any separating characters.\n* `extension` -- Matches the file extension (if any).\n\n\"tag_split_pattern\" should match whatever delimiter separates individual tags\nand will be used with `re.split()`. An example is provided below, which\nmatches the tag format used by\n[TagSpaces](https://github.com/tagspaces/tagspaces):\n\n```json\n\"tag_formats\": [\n {\n \"tag_pattern\": \"(?P.+)(?P\\\\[(?P.+?)\\\\])(?P.*?)\",\n \"tag_split_pattern\": \"\\\\s+\"\n }\n]\n```\n\nMore than one such set of patterns may be provided in a single `tag_formats`\narray, allowing *autotagical* to deal with files tagged in multiple formats in\none run.\n\n### unnamed_patterns\n\n```json\n\"unnamed_patterns\": [\n \"regex pattern 1\",\n \"regex pattern 2\",\n ...\n]\n```\n\nThe various patterns must be valid Python regexes. Each will be used with\n`re.match()` and should match the file names (less tags) of such files to be\ntreated as requiring renaming. They will be matched against the concatenation\nof the `file` and `extension` groups produced by the use of \"tag_pattern\"\nabove, so do not attempt to match against anything not captured by those two\ngroups. An example is provided below, which might match PDF files with\ntimestamps produced by two different scanners:\n\n```json\n\"unnamed_patterns\": [\n \"[0-9]{4}_[0-9]{2}_[0-9]{2}_[0-9]{2}_[0-9]{2}_[0-9]{2}\\\\s*.pdf\",\n \"(Pages\\\\sfrom)?\\\\s*XScan_[0-9]{14}\\\\s*.pdf\"\n]\n```\n\n### renaming_schema\n\n```json\n\"renaming_schemas\": [\n {\n \"filter\": [\"condition 1\", \"condition 2\", ...],\n \"format_string\": \"file name format string\"\n },\n ...\n]\n```\n\n\"renaming_schemas\" is simply a list of filters and an explanation of how to\nname files matching any of them. This list is ordered, and files will be\nrenamed according to the first they match, e.g. if a file has `tag1` and `tag2`\nand the first filter in the array matches `tag2` and the second `tag1`, the\nfile will be renamed according to `tag2`. This allows one to define priorities\nof renaming. See the [Filters](#filters) section for information on filters,\nconditions, and the various operators one may include in them.\n\n\"format_string\" defines how to rename files matching the filter. It cannot\ncontain the `/` character except where it denotes operators (as\nfile names cannot contain `/`). At its simplest, it is simply a string that\nthe file will be renamed to, but that string may include any number/combination\nof operators. See the [Format Strings](#format-strings) section for\ninformation on format strings and the various operators one may include in them.\n\n### movement_schema\n\n```json\n\"movement_schema\": [\n {\n \"filter\": [\"condition 1\", \"condition 2\", ...],\n \"subfolder\": \"\",\n \"sublevels\": [\n {\n \"filter\": [\"condition 3\", \"condition 4\", ...],\n \"subfolder\": \"\",\n \"sublevels\": [...]\n },\n ...\n ]\n },\n ...\n]\n```\n\n\"movement_schema\" defines an output folder hierarchy iteratively by nesting\nfilters. At each folder level, multiple filters can exist that either pass\nfiles to lower subfolders or place them at the current level. These lists are\nordered, and files will be sorted according to the first filter they match,\ne.g. if a file has `tag1` and `tag2` and at a level the first filter in the\narray matches `tag2` and the second `tag1`, the file will be sorted according\nto `tag2`. This allows one to define priorities of sorting. See the\n[Filters](#filters) section for information on filters, conditions, and the\nvarious operators one may include in them.\n\nIf \"subfolder\" contains a format string, it will be interpreted and added to\nthe folder hierarchy that the file will be placed in (and further sorted based\non \"sublevels\"); if it is left blank `\"\"`, files will be placed in the current\n(in the hierarchy) directory without further sorting. If \"sublevels\" is left\nempty `[]`, files will be placed in the specified subfolder without further\nsorting. Note that a movement schema does not have to have a path for every\npossible file. Files that fail to \"find a home\" will be left in the input\nfolder and a warning will be printed (unless `-A` is specified). See the\n[Format Strings](#format-strings) section for information on format strings and\nthe various operators one may include in them.\n\nAdditionally, note that complete hierarchies (i.e. those that terminate with\nexplicitly placing the file in a folder) will be preferred over partial\nhierarchies (i.e. if a file percolates some distance down a hierarchy and then\nmatches no filters). In the event that no complete hierarchy can be found, the\nfirst partial one *will* be used to move the file. It is bad practice to rely\non this behavior though; one should use the `/*|` operator if one explicitly\nwishes absolutely any file that reaches a filter level to reside there.\n\n### Filters\n\nA filter (wherever it might show up in a schema) is defined by an array of\ncondition sets. These condition sets are combined in the logical sense by\n*inclusive or*, i.e. matching at least one condition set is necessary and\nsufficient to match the overall filter. At their simplest, a condition set may\nsimply be a tag, e.g. `\"filter\": [\"tag1\", \"tag2\"]` will match any file with\neither `tag1` or `tag2` (or both) on it. However, the following operators may\nbe used to construct more complex condition sets (whether in filters or in the\nconditional `/?|` operator):\n\n* `/G|` -- The prefix `/G|` is used to denote a tag group instead of a tag\n name, e.g. `\"filter\": [\"/G|Group 1\", \"tag2\"]` will match any file with at\n least one tag in `Group 1` or the tag `tag2` (or both).\n* `/*|` -- The all operator `/*|` matches all files, regardless of how they are\n tagged.\n* `/&|` -- `/&|` is a logical \"and\" operator, requiring matching both\n conditions, e.g. `\"filter\": [\"tag1/&|tag2\"]` will match files that have *both*\n `tag1` and `tag2`. A condition may contain any number of `/&|` operators,\n e.g. one may create the condition `\"tag1/&|tag2/&|/G|Group 1\"`.\n* `/!|` -- The not prefix `/!|` negates the next condition. **This prefix must\n come before any others logically,** i.e. you must write `/!|/G|` rather\n than `/G|/!|` or `/!|/*|` rather than `/*|/!|`. The `/!|` operator\n *can* follow the logical \"and\" operator `/&|`, e.g. `\"/&|/!|\"`,\n which will match any file that has `tag1` and does not have `tag2`.\n\nThere are no (realistic) limits on the degree to which these operators may be\ncombined or how many condition sets a filter might have.\n\n### Format Strings\n\nA format string is simply a string that may or may not contain various\noperators. These operators will be replaced with the corresponding data when\nthe format string is interpreted.\n\n* `/EXT|` -- Anywhere it is put in the format string, `/EXT|` will be replaced\n with the original extension of the file, as defined by the `extension` group\n in the \"tag_formats\" regex that matched the file. This is obviously useful if\n you're renaming multiple types of file and want to preserve extensions. You\n will almost always want to end your format string with `/EXT|`.\n* `/FILE|` -- Anywhere it is put in the format string, `/FILE|` will be\n replaced with the original name of the file, as defined by the `file` group in\n the \"tag_formats\" regex that matched the file.\n* `/TAGS|` -- Anywhere it is put in the format string, `/TAGS|` will be\n replaced with the tags on the original file. **This is necessary to avoid\n your renamed files becoming de-tagged** and should almost always be included\n in a renaming format string.\n* `/?|/T|/F|/E?|` -- The conditional operator\n `/?|` allows for conditional naming. If `` is matched, the entire\n expression will be replaced with ``; if it does not match, the\n entire expression will be replaced with ``. Either text (or both,\n but why would you) may be empty. The conditional operator can take anything\n that can be in a filter condition. See the [Filters](#filters) section for\n information on filters, conditions, and the various operators one may include\n in them. `` and `` may contain other operators, i.e.\n `/EXT|`, `/FILE|`, `/TAGS|`, and `/ITER|`. Note: conditional operators\n **cannot** be nested or contain `/?T|/|` or `/?G|/|` within\n replacement text.\n* `/?T|/|` -- The tag conditional operator `/?T|` will insert the literal\n name of the tag `` if it is present on the file. Note that this is\n equivalent to `/?|/T|//F|/E?|`; it is merely a shortcut.\n* `/?G|/|` -- The tag group conditional operator `/?G|` will insert\n the literal name of the tag group `` if one of its tags is present\n on the file. Note that this is equivalent to `/?|/G|/T|/F|/E?|`; it is merely a shortcut.\n* `/?TIG|/|` -- The \"tag in group\" operator is a special operator\n that will insert a tag on the file that is in the specified tag group. For\n example, `/?TIG|group1?/|` will resolve to `tag1` if `tag1` is on the file and\n in `group1`, or `tag2` if `tag2` is on the file and in `group1`. If multiple\n tags on the file are in the group, the first (in tagging order, left-to-right)\n will be substituted in. If the file lacks a tag in the group, the entire\n operator will simply be blank. This \"tag in group\" operator is most useful\n for writing flexible schema where the exact tags cannot be predicted in\n advance. For example, if one wanted to sort bank statements into folders\n based on what account they are associated with, one could use the \"tag in\n group\" operator with an \"Account Number\" group and then only have to update\n the tag group with the various account number tags, rather than having to\n specify every account number in the schema. As an example, consider the\n following cases, with `Group 1 = tag1, tag3` and\n `format_string = \"Tag: /?TIG|Group 1/|\"`:\n * `File [tag1, tag2]` -- \"Tag: tag1\"\n * `File [tag2, tag4]` -- \"Tag: \"\n * `File [tag1, tag2, tag3]` -- \"Tag: tag2\"\n* `/ITER|/#|/EITER|` -- The `/ITER|` operator is complicated\n but important. It is invoked only in the event that multiple files are going\n to be renamed to the same name. In this case, the text is placed in the file\n name, along with `/#|` being replaced by the n-th file that this is that has\n had the same name. Otherwise, the entirety of the `/ITER|` operator is\n ignored. **The /ITER| operator should not be used in folder name format\n strings. It will be ignored.**\n In essence, the `/ITER|` tag \"counts\" how many times the same file name has\n been produced. It is good practice to always include an `/ITER|` operator in\n your schema to avoid files not being renamed due to potential clobbering.\n `/#|` may appear more than once in an `/ITER|` operator, but there is usually\n no need to. The `/ITER|` operator *may* contain any other operator, including\n the conditional operator `/?|`, but may not be nested. Note that the `/ITER|`\n operator **will not be used** if files end up with the **same name but\n different output directories**. It will only appear if necessary to avoid\n clobbering. An example will make this easier to understand. Consider the\n format string `Widget/ITER| /#|/EITER|` in the following cases:\n * 1 matching file -- The file will be named `Widget`.\n * 3 matching files in same folder -- The files will be named `Widget 1`,\n `Widget 2`, and `Widget 3`.\n * 3 matching files, each in a different folder -- The files will all be named\n `Widget`.\n\n\n\n## Known Issues\n\n* Only POSIX hidden files are considered hidden, i.e. those that begin with a\n`.` dot, not those hidden as Windows does it. This is most likely a **Won\u2019t\nFix**.\n\n\n## Tests\n\n`autotagical` may be tested by cloning this repository and running:\n\n```bash\npython setup.py test\n```\n\nfrom within the root directory. Note that this may require `python3` instead\nof `python`, depending on your *python* installation.\n\n\n## Authors\n\n* **SiriusStarr**\n\n## License\n\nThis project is licensed under the GNU General Public License v3.0 - see the\n[LICENSE.md](LICENSE.md) file for details\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/SiriusStarr/autotagical", "keywords": "file sort tag rename tagging tagspaces", "license": "GPLv3", "maintainer": "", "maintainer_email": "", "name": "autotagical", "package_url": "https://pypi.org/project/autotagical/", "platform": "", "project_url": "https://pypi.org/project/autotagical/", "project_urls": { "Homepage": "https://github.com/SiriusStarr/autotagical" }, "release_url": "https://pypi.org/project/autotagical/1.1.0/", "requires_dist": [ "setuptools", "jsonschema (>=3)", "packaging" ], "requires_python": "", "summary": "A utility to automagically rename and sort tagged files (such as those produced by TagSpaces) according to user-defined schemas.", "version": "1.1.0" }, "last_serial": 5260267, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "11446370c57f037f5fc32790c352c16a", "sha256": "05579d95b84302b8b3ee59289bde180de02eba2182e360cac76a7c1a72ff1bbb" }, "downloads": -1, "filename": "autotagical-1.0.0-py3.7.egg", "has_sig": false, "md5_digest": "11446370c57f037f5fc32790c352c16a", "packagetype": "bdist_egg", "python_version": "3.7", "requires_python": null, "size": 85950, "upload_time": "2019-05-13T00:40:46", "url": "https://files.pythonhosted.org/packages/3f/2c/04efbc40d62f031805182e3fbe394badb6f362292d62fb028cb1859e63ba/autotagical-1.0.0-py3.7.egg" }, { "comment_text": "", "digests": { "md5": "c097c6f7eaaf7cc73c5c6d7eaf851872", "sha256": "765ccd5743be6c3c10334461975ca8bcc41760eb15a7fc36b142f0ba466fcb9e" }, "downloads": -1, "filename": "autotagical-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "c097c6f7eaaf7cc73c5c6d7eaf851872", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 57965, "upload_time": "2019-05-11T03:19:22", "url": "https://files.pythonhosted.org/packages/5b/7f/f480ff735d66dd0f276195a53c27c8fe496428372d3cb982921329f902f4/autotagical-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "613cc3a22b21ec625c3cd57a0a698b6b", "sha256": "5414b20349a97f1eb2471e887231c3e5b8c7e6935a3964141c59ad0f6ec3cbcc" }, "downloads": -1, "filename": "autotagical-1.0.0.tar.gz", "has_sig": false, "md5_digest": "613cc3a22b21ec625c3cd57a0a698b6b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 54629, "upload_time": "2019-05-11T03:19:27", "url": "https://files.pythonhosted.org/packages/b5/ba/97a5d08fe18656aef44591a4774e2c076020b591bffbb2df8b781446d16c/autotagical-1.0.0.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "4dc57d7cb28337b3545b647e3d663cca", "sha256": "3a0e59b443f109b64727a28c6e3817cc0692bd154e04a385d308ba727dc72879" }, "downloads": -1, "filename": "autotagical-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4dc57d7cb28337b3545b647e3d663cca", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 62803, "upload_time": "2019-05-13T00:40:44", "url": "https://files.pythonhosted.org/packages/fd/96/56f048641a5b3c9375dd14c5edb426df39f89b465a4deb8fbef29f2955f3/autotagical-1.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0a19fa5915d63d0d36d637da12222e01", "sha256": "eb8d4a955c6e897fe80f327df19a40138b0e4ab58f1c13738481224656b67d36" }, "downloads": -1, "filename": "autotagical-1.1.0.tar.gz", "has_sig": false, "md5_digest": "0a19fa5915d63d0d36d637da12222e01", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 63102, "upload_time": "2019-05-13T00:40:51", "url": "https://files.pythonhosted.org/packages/d3/32/4a24becac2275fd28066f0bcb8033d0fb4bfb8949b4652fb9c78a74f8fcc/autotagical-1.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "4dc57d7cb28337b3545b647e3d663cca", "sha256": "3a0e59b443f109b64727a28c6e3817cc0692bd154e04a385d308ba727dc72879" }, "downloads": -1, "filename": "autotagical-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4dc57d7cb28337b3545b647e3d663cca", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 62803, "upload_time": "2019-05-13T00:40:44", "url": "https://files.pythonhosted.org/packages/fd/96/56f048641a5b3c9375dd14c5edb426df39f89b465a4deb8fbef29f2955f3/autotagical-1.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0a19fa5915d63d0d36d637da12222e01", "sha256": "eb8d4a955c6e897fe80f327df19a40138b0e4ab58f1c13738481224656b67d36" }, "downloads": -1, "filename": "autotagical-1.1.0.tar.gz", "has_sig": false, "md5_digest": "0a19fa5915d63d0d36d637da12222e01", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 63102, "upload_time": "2019-05-13T00:40:51", "url": "https://files.pythonhosted.org/packages/d3/32/4a24becac2275fd28066f0bcb8033d0fb4bfb8949b4652fb9c78a74f8fcc/autotagical-1.1.0.tar.gz" } ] }