batchmp 1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- batchmp/__init__.py +0 -0
- batchmp/cli/__init__.py +0 -0
- batchmp/cli/base/__init__.py +0 -0
- batchmp/cli/base/bmp_dispatch.py +60 -0
- batchmp/cli/base/bmp_options.py +349 -0
- batchmp/cli/base/vchk.py +47 -0
- batchmp/cli/bmfp/__init__.py +0 -0
- batchmp/cli/bmfp/bmfp_dispatch.py +120 -0
- batchmp/cli/bmfp/bmfp_options.py +442 -0
- batchmp/cli/renamer/__init__.py +0 -0
- batchmp/cli/renamer/renamer_dispatch.py +135 -0
- batchmp/cli/renamer/renamer_options.py +355 -0
- batchmp/cli/tagger/__init__.py +0 -0
- batchmp/cli/tagger/tagger_dispatch.py +143 -0
- batchmp/cli/tagger/tagger_options.py +338 -0
- batchmp/commons/__init__.py +0 -0
- batchmp/commons/chainedhandler.py +102 -0
- batchmp/commons/descriptors.py +173 -0
- batchmp/commons/progressbar.py +154 -0
- batchmp/commons/taskprocessor.py +149 -0
- batchmp/commons/utils.py +194 -0
- batchmp/ffmptools/__init__.py +0 -0
- batchmp/ffmptools/ffcommands/__init__.py +0 -0
- batchmp/ffmptools/ffcommands/cmdopt.py +115 -0
- batchmp/ffmptools/ffcommands/convert.py +130 -0
- batchmp/ffmptools/ffcommands/cuesplit.py +223 -0
- batchmp/ffmptools/ffcommands/denoise.py +173 -0
- batchmp/ffmptools/ffcommands/fragment.py +121 -0
- batchmp/ffmptools/ffcommands/normalize_peak.py +135 -0
- batchmp/ffmptools/ffcommands/segment.py +157 -0
- batchmp/ffmptools/ffcommands/silencesplit.py +159 -0
- batchmp/ffmptools/ffrunner.py +189 -0
- batchmp/ffmptools/ffutils.py +300 -0
- batchmp/ffmptools/processors/__init__.py +0 -0
- batchmp/ffmptools/processors/basefp.py +92 -0
- batchmp/ffmptools/processors/ffentry.py +81 -0
- batchmp/ffmptools/utils/__init__.py +0 -0
- batchmp/ffmptools/utils/cueparse.py +227 -0
- batchmp/ffmptools/utils/cuesheet.py +239 -0
- batchmp/fstools/__init__.py +0 -0
- batchmp/fstools/builders/__init__.py +0 -0
- batchmp/fstools/builders/fsb.py +221 -0
- batchmp/fstools/builders/fsentry.py +60 -0
- batchmp/fstools/builders/fsprms.py +372 -0
- batchmp/fstools/dirtools.py +549 -0
- batchmp/fstools/fsutils.py +272 -0
- batchmp/fstools/rename.py +390 -0
- batchmp/fstools/walker.py +79 -0
- batchmp/tags/__init__.py +0 -0
- batchmp/tags/handlers/__init__.py +0 -0
- batchmp/tags/handlers/basehandler.py +99 -0
- batchmp/tags/handlers/ffmphandler.py +75 -0
- batchmp/tags/handlers/ffmphandlers/__init__.py +0 -0
- batchmp/tags/handlers/ffmphandlers/base.py +243 -0
- batchmp/tags/handlers/mtghandler.py +56 -0
- batchmp/tags/handlers/pmhandler.py +36 -0
- batchmp/tags/handlers/tagsholder.py +264 -0
- batchmp/tags/output/__init__.py +0 -0
- batchmp/tags/output/formatters.py +218 -0
- batchmp/tags/processors/__init__.py +0 -0
- batchmp/tags/processors/basetp.py +266 -0
- batchmp-1.4.dist-info/METADATA +422 -0
- batchmp-1.4.dist-info/RECORD +68 -0
- batchmp-1.4.dist-info/WHEEL +5 -0
- batchmp-1.4.dist-info/entry_points.txt +5 -0
- batchmp-1.4.dist-info/licenses/LICENSE +11 -0
- batchmp-1.4.dist-info/top_level.txt +1 -0
- batchmp-1.4.dist-info/zip-safe +1 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# coding=utf8
|
|
3
|
+
## Copyright (c) 2014 Arseniy Kuznetsov
|
|
4
|
+
##
|
|
5
|
+
## This program is free software; you can redistribute it and/or
|
|
6
|
+
## modify it under the terms of the GNU General Public License
|
|
7
|
+
## as published by the Free Software Foundation; either version 2
|
|
8
|
+
## of the License, or (at your option) any later version.
|
|
9
|
+
##
|
|
10
|
+
## This program is distributed in the hope that it will be useful,
|
|
11
|
+
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
## GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
""" Batch renaming of files and directories
|
|
17
|
+
. supports source directory / source file modes
|
|
18
|
+
. visualises original / targeted folders structure before actual processing
|
|
19
|
+
. supports recursion to specified end_level
|
|
20
|
+
. supports flattening folders beyond specified end_level
|
|
21
|
+
. allows for include / exclude patterns (Unix style)
|
|
22
|
+
. allows global include/exclude of directories and folders
|
|
23
|
+
. display sorting:
|
|
24
|
+
.. by size/date, ascending/descending
|
|
25
|
+
. action commands:
|
|
26
|
+
.. print Prints source directory
|
|
27
|
+
.. index Adds index to files and directories names
|
|
28
|
+
.. add_date Adds date to files and directories names
|
|
29
|
+
.. add_text Adds text to files and directories names
|
|
30
|
+
.. remove Removes n characters from files and directories names
|
|
31
|
+
.. replace RegExp-based replace in files and directories names,
|
|
32
|
+
with support for expandable templates
|
|
33
|
+
.. capitalize Capitalizes words in files / directories names
|
|
34
|
+
.. flatten Flatten all folders below target level, moving the files up
|
|
35
|
+
at the target level. By default, deletes all empty flattened folders
|
|
36
|
+
.. delete Delete selected files and directories
|
|
37
|
+
|
|
38
|
+
Usage: renamer [-h] [-d DIR] [-f FILE] [GLobal Options] {Commands}[Commands Options]
|
|
39
|
+
Input source mode:
|
|
40
|
+
[-d, --dir] Source directory (default is the current directory)
|
|
41
|
+
[-f, --file] File to process
|
|
42
|
+
|
|
43
|
+
Recursion mode:
|
|
44
|
+
[-r, --recursive] Recurse into nested folders
|
|
45
|
+
[-el, --end-level] End level for recursion into nested folders
|
|
46
|
+
|
|
47
|
+
Filter files or folders:
|
|
48
|
+
[-in, --include] Include: Unix-style name patterns separated by ';'
|
|
49
|
+
[-ex, --exclude] Exclude: Unix-style name patterns separated by ';'
|
|
50
|
+
(excludes hidden files by default)
|
|
51
|
+
[-fd, --filter-dirs] Enable Include/Exclude patterns on directories
|
|
52
|
+
[-af, --all-files] Disable Include/Exclude patterns on files
|
|
53
|
+
(shows hidden files excluded by default)
|
|
54
|
+
Miscellaneous:
|
|
55
|
+
[-s, --sort]{na|nd|sa|sd} Sort order for files / folders (name | date, asc | desc)
|
|
56
|
+
[-ni, nested-indent] Indent for printing nested directories
|
|
57
|
+
[-q, --quiet] Do not visualise changes / show messages during processing
|
|
58
|
+
|
|
59
|
+
Commands:
|
|
60
|
+
{print, index, add_date, add_text, remove, replace, capitalize, flatten, delete, version, info}
|
|
61
|
+
$ renamer {command} -h #run this for detailed help on individual commands
|
|
62
|
+
"""
|
|
63
|
+
import sys
|
|
64
|
+
from batchmp.cli.base.bmp_options import BatchMPArgParser, BatchMPHelpFormatter, BatchMPBaseCommands
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class RenamerCommands(BatchMPBaseCommands):
|
|
68
|
+
INDEX = 'index'
|
|
69
|
+
ADD_DATE = 'add_date'
|
|
70
|
+
ADD_TEXT = 'add_text'
|
|
71
|
+
REMOVE = 'remove'
|
|
72
|
+
REPLACE = 'replace'
|
|
73
|
+
CAPITALIZE = 'capitalize'
|
|
74
|
+
FLATTEN = 'flatten'
|
|
75
|
+
DELETE = 'delete'
|
|
76
|
+
STATS = 'stats'
|
|
77
|
+
ORGANIZE = 'organize'
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def commands_meta(cls):
|
|
81
|
+
return ''.join(('{',
|
|
82
|
+
'{}, '.format(cls.PRINT),
|
|
83
|
+
'{}, '.format(cls.INDEX),
|
|
84
|
+
'{}, '.format(cls.ADD_DATE),
|
|
85
|
+
'{}, '.format(cls.ADD_TEXT),
|
|
86
|
+
'{}, '.format(cls.REMOVE),
|
|
87
|
+
'{}, '.format(cls.REPLACE),
|
|
88
|
+
'{}, '.format(cls.CAPITALIZE),
|
|
89
|
+
'{}, '.format(cls.FLATTEN),
|
|
90
|
+
'{}, '.format(cls.DELETE),
|
|
91
|
+
'{}, '.format(cls.STATS),
|
|
92
|
+
'{}, '.format(cls.INFO),
|
|
93
|
+
'{}, '.format(cls.VERSION),
|
|
94
|
+
'{}' .format(cls.ORGANIZE),
|
|
95
|
+
'}'))
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class RenameArgParser(BatchMPArgParser):
|
|
99
|
+
''' Renamer commands parsing
|
|
100
|
+
'''
|
|
101
|
+
def __init__(self):
|
|
102
|
+
self._script_name = 'Renamer'
|
|
103
|
+
self._description = \
|
|
104
|
+
'''
|
|
105
|
+
Renamer is a multi-platform batch rename tool.
|
|
106
|
+
In addition to common rename operations such as
|
|
107
|
+
regexp-based replace, adding text / dates, etc.
|
|
108
|
+
it also supports multi-level indexing across
|
|
109
|
+
nested directories, flattening folders, and
|
|
110
|
+
cleaning up non-media files.
|
|
111
|
+
|
|
112
|
+
As default behavior, Renamer visualises targeted
|
|
113
|
+
changes and ask for confirmation before actually
|
|
114
|
+
changing anything.
|
|
115
|
+
'''
|
|
116
|
+
# Args Parsing
|
|
117
|
+
def parse_commands(self, parser):
|
|
118
|
+
''' Renamer commands parsing
|
|
119
|
+
'''
|
|
120
|
+
# Commands
|
|
121
|
+
subparsers = parser.add_subparsers(dest = 'sub_cmd',
|
|
122
|
+
title = 'Renamer Commands',
|
|
123
|
+
metavar = RenamerCommands.commands_meta())
|
|
124
|
+
self._add_version(subparsers)
|
|
125
|
+
self._add_info(subparsers)
|
|
126
|
+
|
|
127
|
+
def _add_include_mode_group(parser):
|
|
128
|
+
include_mode_group = parser.add_argument_group('Include for processing')
|
|
129
|
+
include_mode_group.add_argument("-id", "--include-dirs", dest = "include_dirs",
|
|
130
|
+
help = "Include directories for processing",
|
|
131
|
+
action = 'store_true')
|
|
132
|
+
include_mode_group.add_argument("-ef", "--exclude-files", dest = "exclude_files",
|
|
133
|
+
help = "Exclude files from processing",
|
|
134
|
+
action = 'store_true')
|
|
135
|
+
|
|
136
|
+
# Print
|
|
137
|
+
print_parser = subparsers.add_parser(RenamerCommands.PRINT,
|
|
138
|
+
description = 'Print source directory',
|
|
139
|
+
formatter_class = BatchMPHelpFormatter)
|
|
140
|
+
print_parser.add_argument('-sl', '--start-level', dest = 'start_level',
|
|
141
|
+
help = 'Initial nested level for printing (0, i.e. root source directory by default)',
|
|
142
|
+
type = int,
|
|
143
|
+
default = 0)
|
|
144
|
+
print_parser.add_argument('-ss', '--show-size', dest = 'show_size',
|
|
145
|
+
help ='Show files size',
|
|
146
|
+
action = 'store_true')
|
|
147
|
+
print_parser.add_argument('-b', '--by', dest = 'by',
|
|
148
|
+
help = 'Show organized virtual view by type or date',
|
|
149
|
+
type = str,
|
|
150
|
+
choices = ['type', 'date'])
|
|
151
|
+
print_parser.add_argument('-df', '--date-format', dest = 'date_format',
|
|
152
|
+
help = 'Date format for subdirectories when using -b date (e.g., %%Y/%%m)',
|
|
153
|
+
type = str,
|
|
154
|
+
default = '%Y-%m-%d')
|
|
155
|
+
|
|
156
|
+
# Stats
|
|
157
|
+
stats_parser = subparsers.add_parser(RenamerCommands.STATS,
|
|
158
|
+
description = 'Prints directory stats',
|
|
159
|
+
formatter_class = BatchMPHelpFormatter)
|
|
160
|
+
stats_parser.add_argument('-ss', '--show-size', dest = 'show_size',
|
|
161
|
+
help ='Show files size',
|
|
162
|
+
action = 'store_true')
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# Flatten
|
|
166
|
+
flatten_parser = subparsers.add_parser(RenamerCommands.FLATTEN,
|
|
167
|
+
description = 'Flatten all folders below target level, moving the files up the target level. \
|
|
168
|
+
By default, all empty flattened folders will be deleted.',
|
|
169
|
+
formatter_class = BatchMPHelpFormatter)
|
|
170
|
+
flatten_parser.add_argument('-tl', '--target-level', dest = 'target_level',
|
|
171
|
+
help = 'Target level below which all folders will be flattened',
|
|
172
|
+
type = int,
|
|
173
|
+
required = True)
|
|
174
|
+
flatten_parser.add_argument('-df', '--discard-flattened', dest = 'discard_flattened',
|
|
175
|
+
help = "What to do with flattened directories: \
|
|
176
|
+
'de' (default) will remove flattened directories if they are empty \
|
|
177
|
+
'le' will leave flattened directories (empty or not) \
|
|
178
|
+
'da' will discard flattened directories even if they are not empty",
|
|
179
|
+
type=str,
|
|
180
|
+
choices = ['de', 'le', 'da'],
|
|
181
|
+
default = 'de')
|
|
182
|
+
self._add_arg_display_curent_state_mode(flatten_parser)
|
|
183
|
+
|
|
184
|
+
# Add index
|
|
185
|
+
add_index_parser = subparsers.add_parser(RenamerCommands.INDEX,
|
|
186
|
+
description = 'Adds index to files and directories names',
|
|
187
|
+
formatter_class = BatchMPHelpFormatter)
|
|
188
|
+
add_index_parser.add_argument('-sf', '--start-from', dest = 'start_from',
|
|
189
|
+
help = 'A number from which the indexing starts (1 by default)',
|
|
190
|
+
type = int,
|
|
191
|
+
default = 1)
|
|
192
|
+
|
|
193
|
+
add_index_type_group = add_index_parser.add_mutually_exclusive_group()
|
|
194
|
+
add_index_type_group.add_argument('-sq', '--sequential', dest = 'sequential',
|
|
195
|
+
help = 'Index selected files sequentially across selected directores. ' \
|
|
196
|
+
'If omitted, the files will instead be indexed within their respective directories (multi-level indexing)',
|
|
197
|
+
action = 'store_true')
|
|
198
|
+
add_index_type_group.add_argument('-bd', '--by-directory', dest = 'by_directory',
|
|
199
|
+
help = 'Index selected files via adding their respective directory counter. ' \
|
|
200
|
+
'If omitted, the files will instead be indexed within their respective directories (multi-level indexing)',
|
|
201
|
+
action = 'store_true')
|
|
202
|
+
add_index_parser.add_argument('-as', '--as-suffix', dest = 'as_suffix',
|
|
203
|
+
help = 'Add index at the end of file names',
|
|
204
|
+
action = 'store_true')
|
|
205
|
+
add_index_parser.add_argument('-js', '--join-string', dest = 'join_str',
|
|
206
|
+
help = "Join string for appending indices (' ' by default)",
|
|
207
|
+
type = str,
|
|
208
|
+
default = ' ')
|
|
209
|
+
add_index_parser.add_argument('-md', '--min-digits', dest = 'min_digits',
|
|
210
|
+
help = 'Minimal number of digits for indexing (2 by default, and adding leading zeros as needed)',
|
|
211
|
+
type = int,
|
|
212
|
+
default = 2)
|
|
213
|
+
_add_include_mode_group(add_index_parser)
|
|
214
|
+
self._add_arg_display_curent_state_mode(add_index_parser)
|
|
215
|
+
|
|
216
|
+
# Add Date
|
|
217
|
+
add_date_parser = subparsers.add_parser(RenamerCommands.ADD_DATE,
|
|
218
|
+
description = 'Adds date to files and directories names',
|
|
219
|
+
formatter_class = BatchMPHelpFormatter)
|
|
220
|
+
add_date_parser.add_argument('-ap', '--as-prefix', dest = 'as_prefix',
|
|
221
|
+
help = 'Add date as a prefix to file names',
|
|
222
|
+
action = 'store_true')
|
|
223
|
+
add_date_parser.add_argument('-js', '--join-string', dest = 'join_str',
|
|
224
|
+
help = "Join string for appending dates ('_' by default)",
|
|
225
|
+
type = str,
|
|
226
|
+
default = '_')
|
|
227
|
+
add_date_parser.add_argument('-fm', '--format', dest = 'format',
|
|
228
|
+
help = 'Date format',
|
|
229
|
+
type = str,
|
|
230
|
+
default = '%Y-%m-%d')
|
|
231
|
+
_add_include_mode_group(add_date_parser)
|
|
232
|
+
self._add_arg_display_curent_state_mode(add_date_parser)
|
|
233
|
+
|
|
234
|
+
# Add Text
|
|
235
|
+
add_text_parser = subparsers.add_parser(RenamerCommands.ADD_TEXT,
|
|
236
|
+
description = 'Adds text to files and directories names',
|
|
237
|
+
formatter_class = BatchMPHelpFormatter)
|
|
238
|
+
add_text_parser.add_argument('-ap', '--asprefix', dest = 'as_prefix',
|
|
239
|
+
help = 'Add text as a prefix to file names',
|
|
240
|
+
action = 'store_true')
|
|
241
|
+
add_text_parser.add_argument('-js', '--join-string', dest = 'join_str',
|
|
242
|
+
help = "Join string for appending text ('_' by default)",
|
|
243
|
+
type = str,
|
|
244
|
+
default = '_')
|
|
245
|
+
add_text_parser.add_argument('-tx', '--text', dest = 'text',
|
|
246
|
+
help = 'Text to add',
|
|
247
|
+
type = str,
|
|
248
|
+
required = True)
|
|
249
|
+
_add_include_mode_group(add_text_parser)
|
|
250
|
+
self._add_arg_display_curent_state_mode(add_text_parser)
|
|
251
|
+
|
|
252
|
+
# Remove chars
|
|
253
|
+
remove_chars_parser = subparsers.add_parser(RenamerCommands.REMOVE,
|
|
254
|
+
description = 'Removes n characters from files and directories names',
|
|
255
|
+
formatter_class = BatchMPHelpFormatter)
|
|
256
|
+
remove_chars_parser.add_argument('-nc', '--num-chars', dest = 'num_chars',
|
|
257
|
+
help = "Number of characters to remove",
|
|
258
|
+
type = int,
|
|
259
|
+
required = True)
|
|
260
|
+
remove_chars_parser.add_argument('-ft', '--from-tail', dest = 'from_tail',
|
|
261
|
+
help = 'Removes text from tail',
|
|
262
|
+
action = 'store_true')
|
|
263
|
+
_add_include_mode_group(remove_chars_parser)
|
|
264
|
+
self._add_arg_display_curent_state_mode(remove_chars_parser)
|
|
265
|
+
|
|
266
|
+
# Replace
|
|
267
|
+
replace_parser = subparsers.add_parser(RenamerCommands.REPLACE,
|
|
268
|
+
description = 'RegExp-based replace in files and directories names. ' \
|
|
269
|
+
'Supports expandable templates, such as ' \
|
|
270
|
+
'$dirname, $pardirname, $atime, $ctime, etc. ' \
|
|
271
|
+
'For media files, also support tag-based templates such as ' \
|
|
272
|
+
'$title, $album, $artist, $albumartist, $genre, $year, $track, etc.',
|
|
273
|
+
formatter_class = BatchMPHelpFormatter)
|
|
274
|
+
replace_parser.add_argument('-fs', '--find-string', dest = 'find_str',
|
|
275
|
+
help = "Find pattern to look for",
|
|
276
|
+
type = str,
|
|
277
|
+
required=True)
|
|
278
|
+
replace_parser.add_argument('-rs', '--replace-string', dest = 'replace_str',
|
|
279
|
+
help = 'Replace pattern to replace with.\
|
|
280
|
+
If not specified and there is a match from the find pattern, \
|
|
281
|
+
the entire string will be replaced with that match. ' \
|
|
282
|
+
'Supports the following expandable templates: ' \
|
|
283
|
+
'$dirname, $pardirname, $adtime, $cdtime, $mdtime, ' \
|
|
284
|
+
'$atime, $ctime, $mtime, $adate, $cdate, $mdate. ' \
|
|
285
|
+
'For media files, also support tag-based templates such as ' \
|
|
286
|
+
'$title, $album, $artist, $albumartist, $genre, $year, $track, etc.',
|
|
287
|
+
type = str)
|
|
288
|
+
replace_parser.add_argument('-ic', '--ignore-case', dest = 'ignore_case',
|
|
289
|
+
help = 'Case insensitive',
|
|
290
|
+
action = 'store_true')
|
|
291
|
+
replace_parser.add_argument('-ie', '--include-extension', dest = 'include_extension',
|
|
292
|
+
help = 'Include file extension',
|
|
293
|
+
action = 'store_true')
|
|
294
|
+
_add_include_mode_group(replace_parser)
|
|
295
|
+
self._add_arg_display_curent_state_mode(replace_parser)
|
|
296
|
+
|
|
297
|
+
# Capitalize
|
|
298
|
+
capitalize_parser = subparsers.add_parser(RenamerCommands.CAPITALIZE,
|
|
299
|
+
description = 'Capitalizes words in files / directories names',
|
|
300
|
+
formatter_class = BatchMPHelpFormatter)
|
|
301
|
+
_add_include_mode_group(capitalize_parser)
|
|
302
|
+
self._add_arg_display_curent_state_mode(capitalize_parser)
|
|
303
|
+
|
|
304
|
+
# Delete
|
|
305
|
+
delete_parser = subparsers.add_parser(RenamerCommands.DELETE,
|
|
306
|
+
description = 'Delete selected files and directories',
|
|
307
|
+
formatter_class = BatchMPHelpFormatter)
|
|
308
|
+
_add_include_mode_group(delete_parser)
|
|
309
|
+
self._add_arg_display_curent_state_mode(delete_parser)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
# Organize
|
|
313
|
+
organize_parser = subparsers.add_parser(RenamerCommands.ORGANIZE,
|
|
314
|
+
description='Organize selected files into directories by specified attributes',
|
|
315
|
+
formatter_class=BatchMPHelpFormatter)
|
|
316
|
+
organize_parser.add_argument('-b', '--by', dest='by',
|
|
317
|
+
help='Organization strategy: by type or by date',
|
|
318
|
+
type=str,
|
|
319
|
+
choices=['type', 'date'],
|
|
320
|
+
required=True)
|
|
321
|
+
organize_parser.add_argument('-df', '--date-format', dest='date_format',
|
|
322
|
+
help='Date format for subdirectories (e.g., %%Y/%%m)',
|
|
323
|
+
type=str,
|
|
324
|
+
default='%Y-%m-%d')
|
|
325
|
+
organize_parser.add_argument('-td', '--target-dir', dest='target_dir',
|
|
326
|
+
help='Target directory to organize files into',
|
|
327
|
+
type=str)
|
|
328
|
+
_add_include_mode_group(organize_parser)
|
|
329
|
+
self._add_arg_display_curent_state_mode(organize_parser)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
# Args Checking
|
|
334
|
+
def default_command(self, args, parser):
|
|
335
|
+
args['sub_cmd'] = RenamerCommands.PRINT
|
|
336
|
+
args['start_level'] = 0
|
|
337
|
+
args['show_size'] = False
|
|
338
|
+
|
|
339
|
+
def check_args(self, args, parser):
|
|
340
|
+
''' Validation of supplied Renamer CLI arguments
|
|
341
|
+
'''
|
|
342
|
+
super().check_args(args, parser)
|
|
343
|
+
|
|
344
|
+
if args['sub_cmd'] == RenamerCommands.FLATTEN:
|
|
345
|
+
if args['file']:
|
|
346
|
+
parser.error('This operation requires a source directory')
|
|
347
|
+
if args['end_level'] <= args['target_level']:
|
|
348
|
+
#print ('Target Level should be greater than or equal to the End Level Global Option\n'
|
|
349
|
+
# '... Adjusting End Level to: {}'.format(args['target_level']))
|
|
350
|
+
args['end_level'] = args['target_level']
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
|
|
File without changes
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# coding=utf8
|
|
3
|
+
## Copyright (c) 2014 Arseniy Kuznetsov
|
|
4
|
+
##
|
|
5
|
+
## This program is free software; you can redistribute it and/or
|
|
6
|
+
## modify it under the terms of the GNU General Public License
|
|
7
|
+
## as published by the Free Software Foundation; either version 2
|
|
8
|
+
## of the License, or (at your option) any later version.
|
|
9
|
+
##
|
|
10
|
+
## This program is distributed in the hope that it will be useful,
|
|
11
|
+
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
## GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
from batchmp.cli.base.bmp_dispatch import BatchMPDispatcher
|
|
16
|
+
from batchmp.cli.tagger.tagger_options import TaggerArgParser, TaggerCommands
|
|
17
|
+
from batchmp.commons.utils import ImageLoader
|
|
18
|
+
from batchmp.tags.processors.basetp import BaseTagProcessor
|
|
19
|
+
from batchmp.tags.handlers.tagsholder import TagHolder
|
|
20
|
+
from batchmp.tags.output.formatters import OutputFormatType
|
|
21
|
+
from batchmp.fstools.builders.fsprms import FSEntryParamsExt
|
|
22
|
+
|
|
23
|
+
class TagsDispatcher(BatchMPDispatcher):
|
|
24
|
+
''' Tagger CLI Commands Dispatcher
|
|
25
|
+
'''
|
|
26
|
+
def __init__(self):
|
|
27
|
+
self.option_parser = TaggerArgParser()
|
|
28
|
+
|
|
29
|
+
# Dispatcher
|
|
30
|
+
def dispatch(self):
|
|
31
|
+
''' Dispatches Tagger commands
|
|
32
|
+
'''
|
|
33
|
+
if not super().dispatch():
|
|
34
|
+
args = self.option_parser.parse_options()
|
|
35
|
+
if args['sub_cmd'] == TaggerCommands.PRINT:
|
|
36
|
+
self.print_dir(args)
|
|
37
|
+
|
|
38
|
+
elif args['sub_cmd'] == TaggerCommands.SET:
|
|
39
|
+
self.set_tags(args)
|
|
40
|
+
|
|
41
|
+
elif args['sub_cmd'] == TaggerCommands.COPY:
|
|
42
|
+
self.copy_tags(args)
|
|
43
|
+
|
|
44
|
+
elif args['sub_cmd'] == TaggerCommands.INDEX:
|
|
45
|
+
self.index(args)
|
|
46
|
+
|
|
47
|
+
elif args['sub_cmd'] == TaggerCommands.REMOVE:
|
|
48
|
+
self.remove_tags(args)
|
|
49
|
+
|
|
50
|
+
elif args['sub_cmd'] == TaggerCommands.REPLACE:
|
|
51
|
+
self.replace_tags(args)
|
|
52
|
+
|
|
53
|
+
elif args['sub_cmd'] == TaggerCommands.CAPITALIZE:
|
|
54
|
+
self.capitalize_tags(args)
|
|
55
|
+
|
|
56
|
+
elif args['sub_cmd'] == TaggerCommands.DETAUCH:
|
|
57
|
+
self.detauch_art(args)
|
|
58
|
+
|
|
59
|
+
else:
|
|
60
|
+
print('Nothing to dispatch')
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
return True
|
|
64
|
+
|
|
65
|
+
# Dispatched Methods
|
|
66
|
+
def print_dir(self, args):
|
|
67
|
+
fs_entry_params = FSEntryParamsExt(args)
|
|
68
|
+
BaseTagProcessor().print_dir(fs_entry_params,
|
|
69
|
+
show_stats = args['show_stats'],
|
|
70
|
+
format = OutputFormatType.FULL if args['full_format'] else OutputFormatType.COMPACT)
|
|
71
|
+
|
|
72
|
+
def set_tags(self, args):
|
|
73
|
+
tag_holder = TagHolder(process_templates = False)
|
|
74
|
+
tag_holder.title = args['title']
|
|
75
|
+
tag_holder.album = args['album']
|
|
76
|
+
tag_holder.artist = args['artist']
|
|
77
|
+
tag_holder.albumartist = args['albumartist']
|
|
78
|
+
tag_holder.genre = args['genre']
|
|
79
|
+
tag_holder.composer = args['composer']
|
|
80
|
+
tag_holder.track = args['track']
|
|
81
|
+
tag_holder.tracktotal = args['tracktotal']
|
|
82
|
+
tag_holder.disc = args['disc']
|
|
83
|
+
tag_holder.disctotal = args['disctotal']
|
|
84
|
+
tag_holder.year = args['year']
|
|
85
|
+
tag_holder.encoder = args['encoder']
|
|
86
|
+
tag_holder.bpm = args['bpm']
|
|
87
|
+
tag_holder.comp = args['compilaton']
|
|
88
|
+
tag_holder.grouping = args['grouping']
|
|
89
|
+
tag_holder.comments = args['comments']
|
|
90
|
+
tag_holder.lyrics = args['lyrics']
|
|
91
|
+
|
|
92
|
+
art, art_path_or_url = None, args['artwork']
|
|
93
|
+
if art_path_or_url:
|
|
94
|
+
art = ImageLoader.load_image(art_path_or_url)
|
|
95
|
+
if art:
|
|
96
|
+
tag_holder.art = art
|
|
97
|
+
|
|
98
|
+
fs_entry_params = FSEntryParamsExt(args)
|
|
99
|
+
BaseTagProcessor().set_tags_visual(fs_entry_params,
|
|
100
|
+
tag_holder = tag_holder,
|
|
101
|
+
diff_tags_only = args['diff_tags_only'])
|
|
102
|
+
|
|
103
|
+
def copy_tags(self, args):
|
|
104
|
+
fs_entry_params = FSEntryParamsExt(args)
|
|
105
|
+
BaseTagProcessor().copy_tags(fs_entry_params,
|
|
106
|
+
tag_holder_path = args['tagholder'],
|
|
107
|
+
diff_tags_only = args['diff_tags_only'])
|
|
108
|
+
|
|
109
|
+
def index(self, args):
|
|
110
|
+
fs_entry_params = FSEntryParamsExt(args)
|
|
111
|
+
BaseTagProcessor().index(fs_entry_params,
|
|
112
|
+
diff_tags_only = args['diff_tags_only'],
|
|
113
|
+
start_from = args['start_from'])
|
|
114
|
+
|
|
115
|
+
def remove_tags(self, args):
|
|
116
|
+
fs_entry_params = FSEntryParamsExt(args)
|
|
117
|
+
BaseTagProcessor().remove_tags(fs_entry_params,
|
|
118
|
+
tag_fields = args['tag_fields'],
|
|
119
|
+
diff_tags_only = args['diff_tags_only'])
|
|
120
|
+
|
|
121
|
+
def replace_tags(self, args):
|
|
122
|
+
fs_entry_params = FSEntryParamsExt(args)
|
|
123
|
+
BaseTagProcessor().replace_tags(fs_entry_params,
|
|
124
|
+
tag_fields = args['tag_fields'], ignore_case = args['ignore_case'],
|
|
125
|
+
find_str = args['find_str'], replace_str = args['replace_str'],
|
|
126
|
+
diff_tags_only = args['diff_tags_only'])
|
|
127
|
+
|
|
128
|
+
def capitalize_tags(self, args):
|
|
129
|
+
fs_entry_params = FSEntryParamsExt(args)
|
|
130
|
+
BaseTagProcessor().capitalize_tags(fs_entry_params,
|
|
131
|
+
tag_fields = args['tag_fields'],
|
|
132
|
+
diff_tags_only = args['diff_tags_only'])
|
|
133
|
+
|
|
134
|
+
def detauch_art(self, args):
|
|
135
|
+
fs_entry_params = FSEntryParamsExt(args)
|
|
136
|
+
BaseTagProcessor().detauch_art(fs_entry_params,
|
|
137
|
+
target_dir = args['target_dir'])
|
|
138
|
+
|
|
139
|
+
def main():
|
|
140
|
+
''' Tagger entry point
|
|
141
|
+
'''
|
|
142
|
+
TagsDispatcher().dispatch()
|
|
143
|
+
|