Tagging

The tagging system in fidx is simple (and limited), but it has one particular quirk which can cause some confusion: Tags are internally associated with hashes, not file entries. This is done based off the assumption that the tags are used to describe the contents of a file, which has two benefits:

  • If a file is renamed1 (without changing its contents) it will not lose its tags.
  • If several files share the same contents, only one will need to be tagged but all of the files will gain the tag(s).

Tags are stored in the fidx tree database, and thus are local to the tree.

Managing tags

In order to tag files there needs to be tags in the database. To add tags use the subcommand add-tag (more than one tag can be added at a time):

$ fidx add-tag some-tag another

(Each tag must be unique).

Once there are tags in the database, use the subcommand list-tags to list them:

$ fidx list-tags
    2 another
    1 some-tag

A tag can be renamed using the rename-tag subcommand. The following would rename a tag called from-name to to-name:

$ fidx rename-tag from-name to-name

(Only one tag can be renamed at a time)

Tags can be removed using the remove-tag subcommand:

$ fidx remove-tag some-tag another

Tagging/Untagging files

Note: It is important to only manage tagging/untagging in a tree which has not been modified since last database update since it associates tags with hashes. Always run and update before managing tag associations in a tree.

To attach one or more tags to a file use the subcommand tag, which by default takes as its first argument the name of the file to tag, and the remaining arguments are tag names:

$ fidx tag fossil-repos-2020.tar scm fossil source-archives

This behavior can be changed by adding an -- argument, which causes all arguments before the -- to be interpreted as a list of files, while arguments after the -- will be interpreted as a list of tags.

$ fidx tag fossil-repos-2020.tar fossil-repos-2021.tar -- scm fossil

A side-effect of this design is that fidx tagging does not work well with files named -- (but naming a file that is kind of asking for trouble, so wish granted).

If a file name or tag argument begins with an @ character, and the string immediately following the @ character is a file name (which exists), this file will be treated as a list of files/tags, depending on where it is specified.

Assuming files.list exists and is a list of files to tag, and tags.list exists and is a list of files to apply to the files in files.list, use:

$ fidx tag @files.list @tags.list

The @-list feature can be combined with --:

$ fidx tag some-file.tar @files.list another-file.tar -- some-tag @tags.list another-tag

Just as the special -- argument implies some weird semantics regarding files called simply --, the @<file/tag> introduces some weirdness surrounding file and tag names with a leading @, and thus this is discouraged.

To inspect what tags a file is associated with use the subcommand tags:

$ fidx tags fossil-repos-2020.tar
list tags for fossil-repos-2020.tar
   2 fossil
   6 scm
   7 source-archives

Removing tags from a file can be done using the untag subcommand, which has the same format as tag; first argument is the file name and the following arguments are the tags to disassociate with that file:

$ fidx untag fossil-repos-2020.tar scm

To search for a file based on tags use the subcommand search:

$ fidx search some-tag another

The search is very basic, and only supports implicit AND boolean searches, meaning that only files with all matching tags will be returned.

To run a command on each entry in an output list from a search on unix-like platforms one can use xargs, though note that it by default treats spaces as argument separators, which causes issues if files/paths have spaces in them. The workaround unfortunately does not look the same on macOS and Linux.

The folloing examples will remove any files from the filesystem that are tagged with the tag "delete-me".

macOS (use tr to convert newlines to nul, tell xargs (using -0) to only separate entries by nul):

$ fidx search delete-me | tr '\n' '\0' | xargs -0 rm

Linux (tell xargs to only use \n as a deliminter (by default this will include spaces):

$ fidx search delete-me | xargs -d '\n' rm

1 fidx has no concept of a file/directory rename; it treats renames as a deletion and a new file, where the deletion would cause the tag association to disappear if tags where associated with file entries rather than their contents.