A beets plugin to copy/moves non-music extra files, attachments, and artifacts during the import process.
Project description
Filetote plugin for beets
A plugin that moves non-music extra files, attachments, and artifacts during the import process for beets, a music library manager (and much more!).
Installing
Stable
The stable version of the plugin is available from PyPI and can be installed
using pip3
:
pip3 install beets-filetote
If you get permission errors, try running it with sudo
.
Development
The development version can be installed from GitHub by using these commands:
git clone https://github.com/gtronset/beets-filetote.git
cd beets-filetote
python3 setup.py install
If you get permission errors, try running it with sudo
.
Update the config.yaml
to utilize the local plugin with:
pluginpath:
- /path/to.../beets-filetote/beetsplug
Configuration
You will need to enable the plugin in beets' config.yaml
:
plugins: filetote
It can copy files by file extension:
filetote:
extensions: .cue .log
Or copy all non-music files:
filetote:
extensions: .*
Or copy files by filename:
filetote:
filenames: song.log
Or match based on a "pattern" (glob pattern):
filetote:
patterns:
artworkdir:
- "[aA]rtwork/"
It can look for and target "pairs" (files having the same name as a matching or "paired" media item/track):
filetote:
pairing:
enabled: true
You can specify pairing to happen to certain extensions, and even target/include only paired files:
filetote:
pairing:
enabled: true
pairing_only: true
extensions: ".lrc"
It can also exclude files by name:
filetote:
exclude: song_lyrics.nfo
And print what got left:
filetote:
print_ignored: true
exclude
-d files take precedence over other matching, meaning exclude will
trump other matches by either extensions
or filenames
.
Matching/Handling Files
In order to collect extra files and artifacts, Filetote needs to be told which types of files it should care about. This can be done using the following:
ext
filename
pattern
Filetote can also grab "paired" files, meaning those files having the same name as a matching media item/track.
Extension (ext
)
Filename can match on the extensio) of the file, in a space-delimited list (string sequence). Take:
filetote:
ext: .lrc .log
Any file with either a .lrc
or .log
will match.
Use .*
to match all file extensions.
Filename
Filetote can match on the actual name (including extension) of the file, in a space-delimited list (string sequence). Take:
filetote:
filenames: cover.jpg artifact.nfo
This will match if the filename of the given artifact or extra file matches the
name exactly as specified, in this example either cover.jpg
or artifact.nfo
.
This will match across any subdirectories, meaning targeting a filename in a
specific subdirectory will not work (this functionality can be achieved using
a pattern
, however).
Pattern
Filetote can match on a given pattern as specified using glob patterns.
Paths in the pattern are relative to the root of the importing album. Hence,
if there are subdirectories in the album's folder (for multidisc setups, for
instance, e.g., albumpath/CD1
), the album's path would be the base/root for
the pattern (ex: CD1/*.jpg
). Patterns will work with or without the
proceeding slash (/
). Note: Windows users will need to obviously use the
appropriate slash (\
).
Take:
filetote:
patterns:
artworkdir:
- "[aA]rtwork/"
This will match all files within the given subdirectory of either artwork/
or Artwork/
. Unless specified, [aA]rtwork/
will grab all non-media files
in that subdirectory irrespective of name or extension (it is equivalent to
[aA]rtwork/*.*
).
Patterns are defined by a name so that any customization for renaming can
apply to the pattern when specifying the path (ex: pattern:artworkdir
; see
the section on renaming below).
Renaming files
Renaming works in much the same way as beets Path Formats, though with only
the below specified fields (this will change in the future). This plugin
supports the below new path queries, which each takes a single corresponding
value. These can be defined in either the top-level paths
section of Beet's
config or in the paths
section of Filetote's config.
New path queries, from most to least specific:
filename:
paired_ext:
pattern:
ext:
Renaming has the following considerations:
- The fields available include the standard metadata values of the imported
item (
$albumartist
,$album
,$title
, etc.), along with Filetote-specific values of:$albumpath
: the entire path of the new destination of the item/track (a useful shorthand for when the extra/artifact file will be moved allongside the item/track)$old_filename
: the filename of the extra/artifact file before its renamed$medianame_old
: the filename of the item/track triggering it, before it's renamed$medianame_new
: the filename of the item/track triggering it, after it's renamed).
- The full set of built in functions are also supported, with the exception of
%aunique
- which will return an empty string. filename:
path query will take precedence overpaired_ext:
,pattern:
, andext:
if a given file qualifies for them.paired_ext:
takes precedence overpattern:
andext:
, but is not required.pattern:
is higher priority thanext:
.
Each template string uses a query syntax for each of the file extensions. For
example the following template string will be applied to .log
files by using
the ext:
query:
paths:
ext:.log: $albumpath/$artist - $album
Or:
filetote:
paths:
ext:.log: $albumpath/$artist - $album
This will rename a log file to:
~/Music/Artist/2014 - Album/Artist - Album.log
Or by using the filename:
query:
paths:
filename:track.log: $albumpath/$artist - $album
Or:
filetote:
paths:
filename:track.log: $albumpath/$artist - $album
This will rename the specific track.log
log file to:
~/Music/Artist/2014 - Album/Artist - Album.log
Note: if the rename is set and there are multiple files that qualify, only the first will be added to the library (new folder); other files that subsequently match will not be saved/renamed. To work around this,
$old_filename
can be used to help with adding uniqueness to the name.
Import Operations
This plugin supports the same operations as beets:
copy
move
link
(symlink)harklink
reflink
These options are mutually exclusive, and there are nuances to how beets (and thus this plugin) behave when there multiple set. See the beets documentation and #36 for more details.
Examples of config.yaml
plugins: filetote
paths:
default: $albumartist/$year - $album/$track - $title
singleton: Singletons/$artist - $title
ext:.log: $albumpath/$artist - $album
ext:.cue: $albumpath/$artist - $album
paired_ext:.lrc: $albumpath/$medianame_old
filename:cover.jpg: $albumpath/cover
filetote:
extensions: .cue .log .jpg
filename: "cover.jpg"
pairing:
enabled: true
extensions: ".lrc"
print_ignored: true
Or:
plugins: filetote
paths:
default: $albumartist/$year - $album/$track - $title
singleton: Singletons/$artist - $title
filetote:
extensions: .cue
patterns:
artworkdir:
- "[sS]cans/"
- "[aA]rtwork/"
pairing:
enabled: true
extensions: ".lrc"
paths:
pattern:artworkdir: $albumpath/artwork
paired_ext:.lrc: $albumpath/$medianame_old
filename:cover.jpg: $albumpath/cover
Multi-Disc and Nested Import Directories
Beets imports multi-disc albums as a single unit (see Beets documentation). By default, this results in the media importing to a single directory in the library. Artifacts and extra files in the initial subdirectories will brought by Filetote to the destination of the file's they're near, resulting in them landing where one would expect. Because of this, the files will also be moved by Filetote to any specified subdirectory in the library if the path definition creates "Disc N" subfolders as described in the beets documentation.
In short, artifacts and extra files in these scenarios should simply just move/copy as expected.
Why Filetote and Not Other Plugins?
Filetote serves the same core purpose as the copyfilertifacts
plugin and the
extrafiles
plugin, however both have lacked in maintenance over the last few
years. There are outstanding bugs in each (though copyfilertifacts
has seen
some recent activity resolving some). In addition, each are lacking in certain
features and abilities, such as hardlink/reflink support, "paired" file handling,
and extending renaming options. What's more, significant focus has been provided
to Filetote around Python3 conventions, linting, and typing in order to promote
healthier code and easier maintenance.
Filetote strives to encompass all functionality that both copyfilertifacts
and extrafiles
provide, and then some!
Migrating from copyfilertifacts
Filetote can be configured using nearly identical configuration as copyfilertifacts
,
simply replacing the name of the plugin in its configuration settings. There
is one change that's needed if all extensions are desired, as Filetote does not
grab all extensions by default (as copyfilertifacts
does). To accommodate,
simply explicitly state all extension using .*
:
filetote:
extensions: .*
Otherwise, simply replacing the name in the config section will work. For example:
copyartifacts:
extensions: .cue .log
Would become:
filetote:
extensions: .cue .log
Path definitions can also be specified in the way that copyfileartifacts
does,
alongside other path definitions for beets. E.g.:
paths:
ext:log: $albumpath/$artist - $album
Migrating from extrafiles
Filetote can be configured using nearly identical configuration as extrafiles
,
simply replacing the name of the plugin in its configuration settings. For example:
extrafiles:
patterns:
all: "*.*"
Would become:
filetote:
patterns:
all: "*.*"
Path definitions can also be specified in the way that extrafiles
does, e.g.:
filetote:
patterns:
artworkdir:
- '[sS]cans/'
- '[aA]rtwork/'
paths:
artworkdir: $albumpath/artwork
Version Upgrade Instructions
Certain versoins require changes to configurations as upgrades occur. Please see below for specific steps for each version.
0.4.0
Default extensions is now None
As of version 0.4.0
, Filetote no longer set the default for extensions
to
.*
. Instead, setting Filetote to collect all extensions needs to be explicitly
defined, e.g.:
filetote:
extensions: .*
Pairing Config Changes
pairing
has been converted from a boolean to an object with other
like-config. Take the following config:
filetote:
pairing: true
pairing_only: false
These will both now be represented as individual settings within pairing
:
filetote:
pairing:
enabled: true
pairing_only: false
extensions: ".lrc"
Both remain optional and both default to false
.
Thanks
This plugin originated as a hard fork from beets-copyartifacts (copyartifacts3).
Thank you to the original work done by Sami Barakat, Adrian Sampson, along with the larger community on beets.
Please report any issues you may have and feel free to contribute.
License
Copyright (c) 2022 Gavin Tronset
Licensed under the MIT license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file beets_filetote-0.4.4.tar.gz
.
File metadata
- Download URL: beets_filetote-0.4.4.tar.gz
- Upload date:
- Size: 19.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.0 CPython/3.10.12 Linux/6.2.0-1016-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7f85310af17661138892a23a033e4cf3b48ee86aadad34ce776733ecc3dec9af |
|
MD5 | 3c094205cf54a04c21a689a0e5d419a4 |
|
BLAKE2b-256 | 8b0647356dd587bd2936cb1d36451e4b5889619925fdb1530dc7a4d0aa100d95 |
File details
Details for the file beets_filetote-0.4.4-py3-none-any.whl
.
File metadata
- Download URL: beets_filetote-0.4.4-py3-none-any.whl
- Upload date:
- Size: 16.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.0 CPython/3.10.12 Linux/6.2.0-1016-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7ed8edd52bfff7de5af17efcbc53d4105bd83d1f79e69763cb9cde7b279a2ad1 |
|
MD5 | deb7fa1d0a4f9747f7bdc01a197d83cf |
|
BLAKE2b-256 | aa9cb073974107bb7be2ebbb730120cf88e9c9adf915bb790447f370d976ce89 |