batchmp 0.99__tar.gz → 1.4__tar.gz

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.
Files changed (78) hide show
  1. batchmp-1.4/LICENSE +11 -0
  2. batchmp-1.4/PKG-INFO +422 -0
  3. {batchmp-0.99 → batchmp-1.4}/README.md +61 -11
  4. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/base/bmp_dispatch.py +2 -2
  5. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/bmfp/bmfp_dispatch.py +3 -1
  6. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/bmfp/bmfp_options.py +8 -3
  7. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/renamer/renamer_dispatch.py +15 -4
  8. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/renamer/renamer_options.py +32 -1
  9. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffcommands/cuesplit.py +3 -3
  10. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffcommands/fragment.py +13 -3
  11. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffcommands/segment.py +7 -7
  12. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffutils.py +5 -5
  13. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/utils/cueparse.py +2 -2
  14. {batchmp-0.99 → batchmp-1.4}/batchmp/fstools/builders/fsb.py +60 -3
  15. {batchmp-0.99 → batchmp-1.4}/batchmp/fstools/builders/fsprms.py +10 -3
  16. {batchmp-0.99 → batchmp-1.4}/batchmp/fstools/dirtools.py +237 -7
  17. {batchmp-0.99 → batchmp-1.4}/batchmp/fstools/rename.py +11 -0
  18. {batchmp-0.99 → batchmp-1.4}/batchmp/fstools/walker.py +2 -2
  19. {batchmp-0.99 → batchmp-1.4}/batchmp/tags/handlers/mtghandler.py +1 -2
  20. {batchmp-0.99 → batchmp-1.4}/batchmp/tags/processors/basetp.py +1 -1
  21. batchmp-1.4/batchmp.egg-info/PKG-INFO +422 -0
  22. {batchmp-0.99 → batchmp-1.4}/batchmp.egg-info/SOURCES.txt +1 -2
  23. {batchmp-0.99 → batchmp-1.4}/batchmp.egg-info/entry_points.txt +0 -1
  24. batchmp-1.4/batchmp.egg-info/requires.txt +4 -0
  25. {batchmp-0.99 → batchmp-1.4}/setup.cfg +2 -2
  26. {batchmp-0.99 → batchmp-1.4}/setup.py +3 -6
  27. batchmp-0.99/PKG-INFO +0 -358
  28. batchmp-0.99/batchmp/tags/extern/mediafile.py +0 -1889
  29. batchmp-0.99/batchmp/tags/processors/__init__.py +0 -0
  30. batchmp-0.99/batchmp.egg-info/PKG-INFO +0 -358
  31. batchmp-0.99/batchmp.egg-info/requires.txt +0 -2
  32. {batchmp-0.99 → batchmp-1.4}/batchmp/__init__.py +0 -0
  33. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/__init__.py +0 -0
  34. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/base/__init__.py +0 -0
  35. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/base/bmp_options.py +0 -0
  36. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/base/vchk.py +0 -0
  37. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/bmfp/__init__.py +0 -0
  38. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/renamer/__init__.py +0 -0
  39. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/tagger/__init__.py +0 -0
  40. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/tagger/tagger_dispatch.py +0 -0
  41. {batchmp-0.99 → batchmp-1.4}/batchmp/cli/tagger/tagger_options.py +0 -0
  42. {batchmp-0.99 → batchmp-1.4}/batchmp/commons/__init__.py +0 -0
  43. {batchmp-0.99 → batchmp-1.4}/batchmp/commons/chainedhandler.py +0 -0
  44. {batchmp-0.99 → batchmp-1.4}/batchmp/commons/descriptors.py +0 -0
  45. {batchmp-0.99 → batchmp-1.4}/batchmp/commons/progressbar.py +0 -0
  46. {batchmp-0.99 → batchmp-1.4}/batchmp/commons/taskprocessor.py +0 -0
  47. {batchmp-0.99 → batchmp-1.4}/batchmp/commons/utils.py +0 -0
  48. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/__init__.py +0 -0
  49. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffcommands/__init__.py +0 -0
  50. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffcommands/cmdopt.py +0 -0
  51. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffcommands/convert.py +0 -0
  52. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffcommands/denoise.py +0 -0
  53. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffcommands/normalize_peak.py +0 -0
  54. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffcommands/silencesplit.py +0 -0
  55. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/ffrunner.py +0 -0
  56. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/processors/__init__.py +0 -0
  57. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/processors/basefp.py +0 -0
  58. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/processors/ffentry.py +0 -0
  59. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/utils/__init__.py +0 -0
  60. {batchmp-0.99 → batchmp-1.4}/batchmp/ffmptools/utils/cuesheet.py +0 -0
  61. {batchmp-0.99 → batchmp-1.4}/batchmp/fstools/__init__.py +0 -0
  62. {batchmp-0.99 → batchmp-1.4}/batchmp/fstools/builders/__init__.py +0 -0
  63. {batchmp-0.99 → batchmp-1.4}/batchmp/fstools/builders/fsentry.py +0 -0
  64. {batchmp-0.99 → batchmp-1.4}/batchmp/fstools/fsutils.py +0 -0
  65. {batchmp-0.99 → batchmp-1.4}/batchmp/tags/__init__.py +0 -0
  66. {batchmp-0.99/batchmp/tags/extern → batchmp-1.4/batchmp/tags/handlers}/__init__.py +0 -0
  67. {batchmp-0.99 → batchmp-1.4}/batchmp/tags/handlers/basehandler.py +0 -0
  68. {batchmp-0.99 → batchmp-1.4}/batchmp/tags/handlers/ffmphandler.py +0 -0
  69. {batchmp-0.99/batchmp/tags/handlers → batchmp-1.4/batchmp/tags/handlers/ffmphandlers}/__init__.py +0 -0
  70. {batchmp-0.99 → batchmp-1.4}/batchmp/tags/handlers/ffmphandlers/base.py +0 -0
  71. {batchmp-0.99 → batchmp-1.4}/batchmp/tags/handlers/pmhandler.py +0 -0
  72. {batchmp-0.99 → batchmp-1.4}/batchmp/tags/handlers/tagsholder.py +0 -0
  73. {batchmp-0.99/batchmp/tags/handlers/ffmphandlers → batchmp-1.4/batchmp/tags/output}/__init__.py +0 -0
  74. {batchmp-0.99 → batchmp-1.4}/batchmp/tags/output/formatters.py +0 -0
  75. {batchmp-0.99/batchmp/tags/output → batchmp-1.4/batchmp/tags/processors}/__init__.py +0 -0
  76. {batchmp-0.99 → batchmp-1.4}/batchmp.egg-info/dependency_links.txt +0 -0
  77. {batchmp-0.99 → batchmp-1.4}/batchmp.egg-info/top_level.txt +0 -0
  78. {batchmp-0.99 → batchmp-1.4}/batchmp.egg-info/zip-safe +0 -0
batchmp-1.4/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ ## Copyright (c) 2016 Arseniy Kuznetsov
2
+ ##
3
+ ## This program is free software; you can redistribute it and/or
4
+ ## modify it under the terms of the GNU General Public License
5
+ ## as published by the Free Software Foundation; either version 2
6
+ ## of the License, or (at your option) any later version.
7
+ ##
8
+ ## This program is distributed in the hope that it will be useful,
9
+ ## but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ ## GNU General Public License for more details.
batchmp-1.4/PKG-INFO ADDED
@@ -0,0 +1,422 @@
1
+ Metadata-Version: 2.4
2
+ Name: batchmp
3
+ Version: 1.4
4
+ Summary: Command-line tools for batch media processing
5
+ Home-page: https://github.com/akpw/batch-mp-tools
6
+ Author: Arseniy Kuznetsov
7
+ Author-email: k.arseniy@gmail.com
8
+ License: GPL-2.0-or-later
9
+ Keywords: batch processing media video audio CLI rename tags ID3
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3.6
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Intended Audience :: End Users/Desktop
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: System Administrators
17
+ Classifier: Intended Audience :: Information Technology
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Topic :: Multimedia :: Sound/Audio
20
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
21
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Conversion
22
+ Classifier: Topic :: Multimedia :: Video
23
+ Classifier: Topic :: Multimedia :: Video :: Conversion
24
+ Classifier: Topic :: Software Development :: Libraries
25
+ Classifier: Topic :: Utilities
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: mutagen>=1.27
29
+ Requires-Dist: pygtrie>=2.3.2
30
+ Requires-Dist: filetype>=1.0.7
31
+ Requires-Dist: mediafile>=0.13.0
32
+ Dynamic: author
33
+ Dynamic: author-email
34
+ Dynamic: classifier
35
+ Dynamic: description
36
+ Dynamic: description-content-type
37
+ Dynamic: home-page
38
+ Dynamic: keywords
39
+ Dynamic: license
40
+ Dynamic: license-file
41
+ Dynamic: requires-dist
42
+ Dynamic: summary
43
+
44
+
45
+ **Status:**
46
+ A rainy weekends project under occasional development :)
47
+
48
+ #### Requirements:
49
+ - [Python 3.4.x](https://www.python.org/download/releases/3.4.1/) or later
50
+
51
+ #### Install:
52
+ - from [PyPI](https://pypi.python.org/pypi/batchmp): `$ pip install batchmp`
53
+ - latest from source repository: `$ pip install git+https://github.com/akpw/batch-mp-tools.git`
54
+
55
+ #### Blogs:
56
+ - [Practical BatchMP](https://akpw.github.io//tags.html#BatchMP+Tools)
57
+ - [Renamer Organize & Virtual Views](https://akpw.github.io/articles/2025/09/22/Print-and-Organize.html)
58
+ - [BatchMP Tools Tutorial](https://akpw.github.io//articles/2015/04/10/batchmp-tutorial-part-i.html)
59
+ - [The BatchMP Tools Project](https://akpw.github.io//articles/2015/03/21/the-batchmp-project.html)
60
+ - [Parallel batch media processing with FFmpeg and Python](https://akpw.github.io//articles/2014/11/24/batch-media-processing-ffmpeg-python.html)
61
+
62
+ ## Description
63
+
64
+ Batch management of media files, from base properties such as file names through tags / artwork metadata to advanced operations on the media content.
65
+
66
+ The project is written in [Python 3.4](https://www.python.org/download/releases/3.4.1/) and currently consists of three main command-line utilities. All three share the core concept of various transformations applied to generated stream of file system entries, and consequently they also share the same set of global options. A quick way to check on that is to run:
67
+ ```
68
+ $ renamer -h
69
+ $ tagger -h
70
+ $ bmfp -h
71
+ ```
72
+ That will show the global options along with specific commands for each tool. Getting more info on the commands level can be done using a similar approach, e.g. to learn more about the `renamer replace` command:
73
+ ```
74
+ $ renamer replace -h
75
+ ```
76
+ By default the tools always visualize targeted changes (whenever possible) before actual processing.
77
+
78
+ A little bit more details on each utility:
79
+
80
+ [**Renamer**](https://github.com/akpw/batch-mp-tools#renamer) is a multi-platform batch rename tool. In addition to common operations such as regexp-based replace, adding text / dates, etc. it also supports advanced operations such as expandable template processing during replace, multi-level indexing across nested directories, flattening folders, organizing files by type or date, etc. The enhanced print command now supports virtual views to preview organization without moving files.
81
+ At its simplest, Renamer can be used to print out the content of current directory:
82
+ ```
83
+ $ renamer
84
+ ```
85
+ Without command arguments, renamer uses `print` as the default command. This is also the case for both `$ tagger` and `$ bmfp`, with each of the tool showing info which is relevant to its intended purpose.
86
+ A little bit more advanced, to see what's lurking at the 7th nested folder level:
87
+ ```
88
+ $ renamer print -sl 7
89
+ ```
90
+ For multi-level indexing of all M4A files in all sub-directories of the current folder:
91
+ ```
92
+ $ renamer -r -in '*.m4a' index
93
+ /Desktop/_test/Gould
94
+ |-/1
95
+ |- 01 Glenn Gould French Suite 1 In D, BWV812 1 Allemande.m4a
96
+ |- 02 Glenn Gould French Suite 1 In D, BWV812 2 Courante.m4a
97
+ |- 03 Glenn Gould French Suite 1 In D, BWV812 3 Sarabande.m4a
98
+ |-/2
99
+ |- 01 Bach, Johann Sebastian French Suite 5 In G Major, BWV816 1 Allemande.m4a
100
+ |- 02 Bach, Johann Sebastian French Suite 5 In G Major, BWV816 2 Courante.m4a
101
+ |- 03 Bach, Johann Sebastian French Suite 5 In G Major, BWV816 3 Sarabande.m4a
102
+ |-/_Art
103
+ 6 files, 3 folders
104
+
105
+ Proceed? [y/n]:
106
+ ```
107
+ Sequential indexing is supported as well using the `-sq` switch. An important detail here, by default Renamer is visualizing the targeted changes and asking for permission to proceed before actually doing anything.
108
+
109
+ For organizing files by media type:
110
+ ```
111
+ $ renamer organize -b type
112
+ ~/Downloads
113
+ |- image/
114
+ |- photo1.jpg
115
+ |- screenshot.png
116
+ |- video/
117
+ |- movie.mp4
118
+ |- audio/
119
+ |- song.mp3
120
+
121
+ Proceed? [y/n]:
122
+ ```
123
+
124
+ Or preview how files would look organized by date without moving them:
125
+ ```
126
+ $ renamer print -b date --date-format "%Y/%m"
127
+ Virtual view by date:
128
+ ~/Downloads
129
+ |- 2025/
130
+ |- 01/
131
+ |- document.pdf
132
+ |- photo.jpg
133
+ |- 02/
134
+ |- video.mp4
135
+ ```
136
+
137
+
138
+
139
+ [**Tagger**](https://github.com/akpw/batch-mp-tools#tagger) manages media metadata, such as tags and artwork. Setting those in selected media file over multiple nested directories now becomes a breeze, with just a few simple commands working uniformly over almost any practically imaginable audio / video media formats. While easy to use, Tagger supports advanced metadata manipulation such as regexp-based replace, expandable template processing, etc. For example, to set the title tag to respective file names followed by the values of track and tracktotal tags:
140
+ ```
141
+ $ tagger -r -in '*BWV816 1*' set --title '$filename, $track of $tracktotal'
142
+ Targeted after processing:
143
+ /Desktop/_test/Gould
144
+ |-/1
145
+ |-/2
146
+ |- Bach, Johann Sebastian French Suite 5 In G Major, BWV816 1 Allemande.m4a
147
+ Title: Bach, Johann Sebastian French Suite 5 In G Major, BWV816 1 Allemande, 1 of 26
148
+ Album: Bach French Suites BWV 812-817 Vol. II; Glenn Gould
149
+ Artist: Glenn Gould
150
+ Album Artist: Glenn Gould
151
+ Genre: Classical
152
+ Composer: Johann Sebastian Bach (1685-1750)
153
+ Year: 1994
154
+ Track: 1/26
155
+ Disk: 2/2
156
+ |-/Art
157
+ 1 files, 3 folders
158
+
159
+ Proceed? [y/n]: n
160
+ ```
161
+ The commands above show some of the available global options: `-r` for recursion into nested folders and `-in` to select media files. In the example above just one file was selected (for the sake of output brevity), which also could be achived via using `-f` for the file source mode.
162
+
163
+
164
+ [**BMFP**](https://github.com/akpw/batch-mp-tools/blob/master/README.md#bmfp-requires-ffmpeg) is all about efficient media content processing, such as conversion between various formats, normalizing sound volume, segmenting / fragmenting media files, denoising audio, detaching individual audio / video streams, etc. As processing media files can typically be resource consuming, BMFP is designed to take advantage of multi-core processors. By default, it automatically breaks up jobs into individual tasks that are then run as separate processes on available CPU cores.
165
+ **BMFP is built on top of [FFmpeg](http://ffmpeg.org/download.html), which needs to be installed and available in the command line**. BMFP can be thought of as a batch FFmpeg runner, intended to make common uses of FFmpeg easy while not restricting its full power.
166
+
167
+ For example, to convert all files from the above example from M4A to FLAC:
168
+ ```
169
+ $ bmfp -r convert -la -tf FLAC
170
+ ```
171
+ The `-tf` switch specifies the target format, while `-la` explicitly tells BMFP to do a lossless conversion.
172
+
173
+ To check on the result, lets's just use the [tagger's](https://github.com/akpw/batch-mp-tools#tagger) ability to print media files info:
174
+ ```
175
+ $ tagger -r -in '*BWV816 1*' print -st -ss
176
+ /Users/AKPower/Desktop/_test/Gould
177
+ |-/1
178
+ |-/2
179
+ |- 7.4MB Bach, Johann Sebastian French Suite 5 in G major, BWV816 1 Allemande.flac
180
+ Title: French Suite 5 in G major, BWV 816 - 1 Allemande
181
+ Album: Bach French Suites BWV 812-817 Vol. II; Glenn Gould
182
+ Artist: Glenn Gould
183
+ Album Artist: Glenn Gould
184
+ Genre: Classical
185
+ Composer: Johann Sebastian Bach (1685-1750)
186
+ Year: 1994
187
+ Track: 1/26
188
+ Disk: 2/2
189
+ Format: FLAC
190
+ Duration: 0:01:48, Bit rate: 548kb/s, Sample rate: 44100Hz, Bit depth: 16
191
+ |-/_backup_15Mar25_094341
192
+ |- 7.9MB Bach, Johann Sebastian French Suite 5 in G major, BWV816 1 Allemande.m4a
193
+ Title: French Suite 5 in G major, BWV 816 - 1 Allemande
194
+ Album: Bach French Suites BWV 812-817 Vol. II; Glenn Gould
195
+ Artist: Glenn Gould
196
+ Album Artist: Glenn Gould
197
+ Genre: Classical
198
+ Composer: Johann Sebastian Bach (1685-1750)
199
+ Year: 1994
200
+ Track: 1/26
201
+ Disk: 2/2
202
+ Format: ALAC
203
+ Duration: 0:01:48, Bit rate: 579kb/s, Sample rate: 44100Hz, Bit depth: 16
204
+ |-/Art
205
+ 2 files, 4 folders
206
+ Total size: 15.2MB
207
+ ```
208
+ From a brief glance, all looks OK. BMFP used FFmpeg to do the actual conversion, while taking care of all other things like preserving tags / artwork, etc.
209
+
210
+ I will follow up with more examples and common use-cases in future blogs.
211
+
212
+
213
+ ## Brief Description of CLI Commands (use -h to expand on details for individual commands)
214
+ ### renamer
215
+ Batch renaming of files and directories
216
+ . source directory or source file modes
217
+ . visualises original / targeted folders structure before actual processing
218
+ . supports recursion, can optionally stop at specified end_level
219
+ . supports flattening folders beyond specified target_level
220
+ . supports include / exclude patterns (Unix style)
221
+ . display sorting:
222
+ .. by size/date, ascending/descending
223
+ . action commands:
224
+ .. print Prints source directory. Enhanced with virtual organization views:
225
+ $ renamer print -b type # Preview organize by media type
226
+ $ renamer print -b date -df "%Y/%m" # Preview organize by date
227
+ .. flatten Flatten all folders below target level, moving the
228
+ files up at the target level. By default, deletes all empty flattened folders
229
+ .. index Adds index to files and directories names
230
+ .. replace RegExp-based replace in files and directories names. Supports expandable templates,
231
+ such as $dirname, $pardirname, $atime, $ctime, etc. For media files, also can process
232
+ tag-based templates such as $title, $album, $artist, $albumartist, $genre, $year, $track,
233
+ etc.
234
+ .. add_date Adds date to files and directories names
235
+ .. add_text Adds text to files and directories names
236
+ .. remove Removes n characters from files and directories names
237
+ .. capitalize Capitalizes words in files / directories names
238
+ .. delete Delete selected files and directories
239
+ .. organize Organizes files into subdirectories based on their attributes:
240
+ $ renamer organize -b type # By media type (image/, video/, audio/)
241
+ $ renamer organize -b date -df "%Y-%m" # By date (2025-01/, 2025-02/)
242
+ $ renamer organize -b date -df "%Y/%m" -td ~/Sorted # To target directory
243
+
244
+ Usage: renamer [-h] [-d DIR] [-f FILE] [Global Options] {Commands} [Commands Options]
245
+ Global Options:
246
+ Input source mode:
247
+ [-d, --dir] Source directory (default is the current directory)
248
+ [-f, --file] File to process
249
+
250
+ Recursion mode:
251
+ [-r, --recursive] Recurse into nested folders
252
+ [-el, --end-level] End level for recursion into nested folders
253
+
254
+ Filter files or folders:
255
+ [-in, --include] Include: Unix-style name patterns separated by ';'
256
+ [-ex, --exclude] Exclude: Unix-style name patterns separated by ';'
257
+ (excludes hidden files by default)
258
+ [-fd, --filter-dirs] Enable Include/Exclude patterns on directories
259
+ [-af, --all-files] Disable Include/Exclude patterns on files
260
+ (shows hidden files excluded by default)
261
+ Miscellaneous:
262
+ [-s, --sort]{na|nd|sa|sd} Sort order for files / folders (name | date, asc | desc)
263
+ [-ni, nested-indent] Indent for printing nested directories
264
+ [-q, --quiet] Do not visualise changes / show messages during processing
265
+
266
+ Commands:
267
+ {print, index, add_date, add_text, remove, replace, capitalize, flatten, delete, organize, version, info}
268
+ $ renamer {command} -h #run this for detailed help on individual commands
269
+
270
+ ### tagger
271
+ ###### Supported formats:
272
+ 'MP3', 'MP4', 'M4A', M4V', 'AIFF', 'ASF', 'QuickTime / MOV',
273
+ 'FLAC', 'MonkeysAudio', 'Musepack',
274
+ 'Ogg FLAC', 'Ogg Speex', 'Ogg Theora', 'Ogg Vorbis',
275
+ 'True Audio', 'WavPack', 'OptimFROG' <p>
276
+ Support via FFmpeg: 'AVI', 'FLV', 'MKV', 'MKA'
277
+
278
+ Batch management of media files metadata (tags & artwork)
279
+ . source directory / source file modes
280
+ . visualises original / targeted files metadata structure
281
+ . supports recursion, can optionally stop at specified end_level
282
+ . include / exclude patterns (Unix style)
283
+ . display sorting:
284
+ .. by size/date, ascending/descending
285
+ . action commands:
286
+ .. print Prints media info
287
+ .. set Sets tags in media files, including artwork, e.g:
288
+ $ tagger set --album 'The Album' -art '~/Desktop/art.jpg'
289
+ Supports expandable templates. To specify a template value,
290
+ use the long tag field name preceded by $:
291
+ $ tagger set --title '$title, $track of $tracktotal'
292
+ In addition to tag fields templates, file system names are also supported:
293
+ $ tagger set --title '$filename' --album '$dirname' --artist '$pardirname'...
294
+ .. copy Copies tags from a specified media file
295
+ .. index Indexes Track / Track Total tags
296
+ .. remove Removes tags from media files
297
+ .. replace RegExp-based replace in specified tags
298
+ e.g., to remove the first three characters in title:
299
+ $ tagger replace -tf 'title' -fs '^[\s\S]{0,3}' -rs ''
300
+ .. capitalize Capitalizes words in specified tags
301
+ .. detauch Extracts artwork
302
+
303
+ Usage: tagger [-h] [-d DIR] [-f FILE] [Global Options] {Commands} [Commands Options]
304
+ Global Options:
305
+ Input source mode:
306
+ [-d, --dir] Source directory (default is the current directory)
307
+ [-f, --file] File to process
308
+
309
+ Recursion mode:
310
+ [-r, --recursive] Recurse into nested folders
311
+ [-el, --end-level] End level for recursion into nested folders
312
+
313
+ Filter files or folders:
314
+ [-in, --include] Include: Unix-style name patterns separated by ';'
315
+ [-ex, --exclude] Exclude: Unix-style name patterns separated by ';'
316
+ (excludes hidden files by default)
317
+ [-fd, --filter-dirs] Enable Include/Exclude patterns on directories
318
+ [-af, --all-files] Disable Include/Exclude patterns on files
319
+ (shows hidden files excluded by default)
320
+ Miscellaneous:
321
+ [-s, --sort]{na|nd|sa|sd} Sort order for files / folders (name | date, asc | desc)
322
+ [-ni, nested-indent] Indent for printing nested directories
323
+ [-q, --quiet] Do not visualise changes / show messages during processing
324
+
325
+ Commands:
326
+ {print, set, copy, index, remove, replace, capitalize, detauch, version, info}
327
+ $ tagger {command} -h #run this for detailed help on individual commands
328
+
329
+ ### bmfp (requires [FFmpeg](http://ffmpeg.org/download.html))
330
+ Batch processing of media files
331
+ . Uses multiprocessing to utilize available CPU cores
332
+ . source directory / source file modes
333
+ . recursion to specified end_level
334
+ . include / exclude patterns (Unix style)
335
+ . action commands:
336
+ .. print Prints media files
337
+ .. convert Converts media to specified format
338
+ For example, to convert all files in current directory
339
+ $ bmfp convert -la -tf FLAC
340
+ .. normalize Nomalizes sound volume in media files
341
+ Peak normalization supported, RMS normalizations TBD
342
+ .. fragment Extract a media file fragment
343
+ .. segment Splits media files into segments
344
+ For example, to split media files in segments of 45 mins:
345
+ $ bmfp segment -d 45:00
346
+ .. silencesplit Splits media files into segments via detecting specified silence
347
+ $ bmfp silencesplit
348
+ .. cuesplit Splits media files into parts with specified output format,
349
+ according to their respective cue sheets
350
+ For example, to split all cue files in the current directory
351
+ $ bmfp cuesplit -tf mp3
352
+ .. denoise Reduces background audio noise in media files
353
+
354
+ .. adjust volume TDB: Adjust audio volume
355
+ .. speed up TDB: Uses Time Stretching to increase audio / video speed
356
+ .. slow down TDB: Uses Time Stretching to increase audio / video speed
357
+
358
+ Usage: bmfp [-h] [-d DIR] [-f FILE] [GLobal Options] {Commands}[Commands Options]
359
+ Input source mode:
360
+ [-d, --dir] Source directory (default is the current directory)
361
+ [-f, --file] File to process
362
+
363
+ Recursion mode:
364
+ [-r, --recursive] Recurse into nested folders
365
+ [-el, --end-level] End level for recursion into nested folders
366
+
367
+ Filter files or folders:
368
+ [-in, --include] Include: Unix-style name patterns separated by ';'
369
+ [-ex, --exclude] Exclude: Unix-style name patterns separated by ';'
370
+ (excludes hidden files by default)
371
+ [-fd, --filter-dirs] Enable Include/Exclude patterns on directories
372
+ [-af, --all-files] Disable Include/Exclude patterns on files
373
+ (shows hidden files excluded by default)
374
+
375
+ Target output Directory Target output directory. When omitted, will be
376
+ [-td, --target-dir] automatically created inside the parent level of
377
+ the input source. For recursive processing,
378
+ the processed files directory structure there
379
+ will be the same as for the original files.
380
+ FFmpeg General Output Options:
381
+ [-ma, --map-all] Force including all streams from the input file
382
+ [-cc, --copy-codecs] Copy streams codecs without re-encoding
383
+ [-vn, --no-video] Exclude video streams from the output
384
+ [-an, --no-audio] Exclude audio streams from the output
385
+ [-sn, --no-subs] Exclude subtitles streams from the output
386
+ [-fo, --ffmpeg-options] Additional FFmpeg options
387
+
388
+ FFmpeg Commands Execution:
389
+ [-q, --quiet] Do not visualise changes / show messages during processing
390
+ [-se, --serial-exec] Run all task's commands in a single process
391
+
392
+ Commands:
393
+ {print, convert, normalize, fragment, segment, silencesplit, cuesplit, denoise, version, info}
394
+ $ bmfp {command} -h #run this for detailed help on individual commands
395
+
396
+
397
+ ## Installing Development version
398
+ - Clone the repo, then run: `$ python -m pip install .`
399
+
400
+ ## Running Tests
401
+
402
+ **Using pytest (recommended):**
403
+ ```bash
404
+ $ pytest -v --tb=short # Run all tests with verbose output
405
+ $ pytest tests/ # Run all tests
406
+ $ pytest tests/fs/test_fs_organize.py # Test organize functionality
407
+ $ pytest tests/fs/test_fsutils.py # Test core filesystem utilities
408
+ $ pytest tests/cli/test_renamer_cli.py # Test renamer CLI
409
+ $ pytest -k "test_organize" # Run tests matching pattern
410
+ ```
411
+
412
+ **Using unittest (fallback):**
413
+ ```bash
414
+ $ python -m unittest discover tests -v # Run all tests with verbose output
415
+ $ python -m unittest tests.fs.test_fs_organize # Run specific test module
416
+ ```
417
+
418
+
419
+
420
+
421
+
422
+
@@ -10,10 +10,11 @@ A rainy weekends project under occasional development :)
10
10
  - latest from source repository: `$ pip install git+https://github.com/akpw/batch-mp-tools.git`
11
11
 
12
12
  #### Blogs:
13
- - [Practical BatchMP](http://www.akpdev.com/tags.html#BatchMP+Tools)
14
- - [BatchMP Tools Tutorial](http://www.akpdev.com/articles/2015/04/10/batchmp-tutorial-part-i.html)
15
- - [The BatchMP Tools Project](http://www.akpdev.com/articles/2015/03/21/the-batchmp-project.html)
16
- - [Parallel batch media processing with FFmpeg and Python](http://www.akpdev.com/articles/2014/11/24/batch-media-processing-ffmpeg-python.html)
13
+ - [Practical BatchMP](https://akpw.github.io//tags.html#BatchMP+Tools)
14
+ - [Renamer Organize & Virtual Views](https://akpw.github.io/articles/2025/09/22/Print-and-Organize.html)
15
+ - [BatchMP Tools Tutorial](https://akpw.github.io//articles/2015/04/10/batchmp-tutorial-part-i.html)
16
+ - [The BatchMP Tools Project](https://akpw.github.io//articles/2015/03/21/the-batchmp-project.html)
17
+ - [Parallel batch media processing with FFmpeg and Python](https://akpw.github.io//articles/2014/11/24/batch-media-processing-ffmpeg-python.html)
17
18
 
18
19
  ## Description
19
20
 
@@ -33,7 +34,7 @@ By default the tools always visualize targeted changes (whenever possible) befor
33
34
 
34
35
  A little bit more details on each utility:
35
36
 
36
- [**Renamer**](https://github.com/akpw/batch-mp-tools#renamer) is a multi-platform batch rename tool. In addition to common operations such as regexp-based replace, adding text / dates, etc. it also supports advanced operations such as expandable template processing during replace, multi-level indexing across nested directories, flattening folders, and cleaning up non-media files.
37
+ [**Renamer**](https://github.com/akpw/batch-mp-tools#renamer) is a multi-platform batch rename tool. In addition to common operations such as regexp-based replace, adding text / dates, etc. it also supports advanced operations such as expandable template processing during replace, multi-level indexing across nested directories, flattening folders, organizing files by type or date, etc. The enhanced print command now supports virtual views to preview organization without moving files.
37
38
  At its simplest, Renamer can be used to print out the content of current directory:
38
39
  ```
39
40
  $ renamer
@@ -62,6 +63,34 @@ For multi-level indexing of all M4A files in all sub-directories of the current
62
63
  ```
63
64
  Sequential indexing is supported as well using the `-sq` switch. An important detail here, by default Renamer is visualizing the targeted changes and asking for permission to proceed before actually doing anything.
64
65
 
66
+ For organizing files by media type:
67
+ ```
68
+ $ renamer organize -b type
69
+ ~/Downloads
70
+ |- image/
71
+ |- photo1.jpg
72
+ |- screenshot.png
73
+ |- video/
74
+ |- movie.mp4
75
+ |- audio/
76
+ |- song.mp3
77
+
78
+ Proceed? [y/n]:
79
+ ```
80
+
81
+ Or preview how files would look organized by date without moving them:
82
+ ```
83
+ $ renamer print -b date --date-format "%Y/%m"
84
+ Virtual view by date:
85
+ ~/Downloads
86
+ |- 2025/
87
+ |- 01/
88
+ |- document.pdf
89
+ |- photo.jpg
90
+ |- 02/
91
+ |- video.mp4
92
+ ```
93
+
65
94
 
66
95
 
67
96
  [**Tagger**](https://github.com/akpw/batch-mp-tools#tagger) manages media metadata, such as tags and artwork. Setting those in selected media file over multiple nested directories now becomes a breeze, with just a few simple commands working uniformly over almost any practically imaginable audio / video media formats. While easy to use, Tagger supports advanced metadata manipulation such as regexp-based replace, expandable template processing, etc. For example, to set the title tag to respective file names followed by the values of track and tracktotal tags:
@@ -149,7 +178,9 @@ I will follow up with more examples and common use-cases in future blogs.
149
178
  . display sorting:
150
179
  .. by size/date, ascending/descending
151
180
  . action commands:
152
- .. print Prints source directory
181
+ .. print Prints source directory. Enhanced with virtual organization views:
182
+ $ renamer print -b type # Preview organize by media type
183
+ $ renamer print -b date -df "%Y/%m" # Preview organize by date
153
184
  .. flatten Flatten all folders below target level, moving the
154
185
  files up at the target level. By default, deletes all empty flattened folders
155
186
  .. index Adds index to files and directories names
@@ -162,6 +193,10 @@ I will follow up with more examples and common use-cases in future blogs.
162
193
  .. remove Removes n characters from files and directories names
163
194
  .. capitalize Capitalizes words in files / directories names
164
195
  .. delete Delete selected files and directories
196
+ .. organize Organizes files into subdirectories based on their attributes:
197
+ $ renamer organize -b type # By media type (image/, video/, audio/)
198
+ $ renamer organize -b date -df "%Y-%m" # By date (2025-01/, 2025-02/)
199
+ $ renamer organize -b date -df "%Y/%m" -td ~/Sorted # To target directory
165
200
 
166
201
  Usage: renamer [-h] [-d DIR] [-f FILE] [Global Options] {Commands} [Commands Options]
167
202
  Global Options:
@@ -186,7 +221,7 @@ I will follow up with more examples and common use-cases in future blogs.
186
221
  [-q, --quiet] Do not visualise changes / show messages during processing
187
222
 
188
223
  Commands:
189
- {print, index, add_date, add_text, remove, replace, capitalize, flatten, delete, version, info}
224
+ {print, index, add_date, add_text, remove, replace, capitalize, flatten, delete, organize, version, info}
190
225
  $ renamer {command} -h #run this for detailed help on individual commands
191
226
 
192
227
  ### tagger
@@ -295,7 +330,7 @@ Support via FFmpeg: 'AVI', 'FLV', 'MKV', 'MKA'
295
330
  (shows hidden files excluded by default)
296
331
 
297
332
  Target output Directory Target output directory. When omitted, will be
298
- [-td, --target-dir] automatically created at the parent level of
333
+ [-td, --target-dir] automatically created inside the parent level of
299
334
  the input source. For recursive processing,
300
335
  the processed files directory structure there
301
336
  will be the same as for the original files.
@@ -317,10 +352,25 @@ Support via FFmpeg: 'AVI', 'FLV', 'MKV', 'MKA'
317
352
 
318
353
 
319
354
  ## Installing Development version
320
- - Clone the repo, then run: `$ python setup.py develop`
355
+ - Clone the repo, then run: `$ python -m pip install .`
356
+
357
+ ## Running Tests
358
+
359
+ **Using pytest (recommended):**
360
+ ```bash
361
+ $ pytest -v --tb=short # Run all tests with verbose output
362
+ $ pytest tests/ # Run all tests
363
+ $ pytest tests/fs/test_fs_organize.py # Test organize functionality
364
+ $ pytest tests/fs/test_fsutils.py # Test core filesystem utilities
365
+ $ pytest tests/cli/test_renamer_cli.py # Test renamer CLI
366
+ $ pytest -k "test_organize" # Run tests matching pattern
367
+ ```
321
368
 
322
- **Running Tests**
323
- - Run via: `$ python setup.py test`
369
+ **Using unittest (fallback):**
370
+ ```bash
371
+ $ python -m unittest discover tests -v # Run all tests with verbose output
372
+ $ python -m unittest tests.fs.test_fs_organize # Run specific test module
373
+ ```
324
374
 
325
375
 
326
376
 
@@ -12,7 +12,7 @@
12
12
  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  ## GNU General Public License for more details.
14
14
 
15
- import pkg_resources
15
+ from importlib import metadata
16
16
  import batchmp.cli.base.vchk
17
17
  from batchmp.cli.base.bmp_options import BatchMPArgParser, BatchMPBaseCommands
18
18
 
@@ -43,7 +43,7 @@ class BatchMPDispatcher:
43
43
  def print_version(self):
44
44
  ''' Prints BatchMP version info
45
45
  '''
46
- version = pkg_resources.require("batchmp")[0].version
46
+ version = metadata.version("batchmp")
47
47
  print('BatchMP tools version {}'.format(version))
48
48
 
49
49
  def print_info(self):
@@ -94,7 +94,9 @@ class BMFPDispatcher(BatchMPDispatcher):
94
94
  ff_entry_params = FFEntryParamsExt(args)
95
95
  Fragmenter().fragment(ff_entry_params,
96
96
  fragment_starttime = args['fragment_starttime'].total_seconds(),
97
- fragment_duration = args['fragment_duration'].total_seconds())
97
+ fragment_duration = args['fragment_duration'].total_seconds(),
98
+ fragment_trim = args['fragment_trim'].total_seconds(),
99
+ )
98
100
 
99
101
  def segment(self, args):
100
102
  ff_entry_params = FFEntryParamsExt(args)
@@ -146,8 +146,9 @@ class BMFPArgParser(BatchMPArgParser):
146
146
  target_output_group = parser.add_argument_group('Target Output Directory')
147
147
  target_output_group.add_argument("-td", "--target-dir", dest = "target_dir",
148
148
  type = lambda d: self._is_valid_dir_path(parser, d),
149
+ default = '.',
149
150
  help = "Target output directory. When omitted, will be automatically "
150
- "created at the parent level of the input source. "
151
+ "created inside the parent level of the input source. "
151
152
  "For recursive processing, the processed files directory structure there "
152
153
  "will be the same as for the original files.")
153
154
 
@@ -246,14 +247,18 @@ class BMFPArgParser(BatchMPArgParser):
246
247
  description = 'Extracts a fragment via specified start time & duration',
247
248
  formatter_class = BatchMPHelpFormatter)
248
249
  group = fragment_parser.add_argument_group('Fragment parameters')
249
- group.add_argument('-fs', '--starttime', dest='fragment_starttime',
250
+ group.add_argument('-fs', '--start', dest='fragment_starttime',
250
251
  help = 'Fragment start time, in seconds or in the "hh:mm:ss[.xxx]" format',
251
252
  type = lambda f: self._is_timedelta(parser, f),
252
253
  required = True)
253
254
  group.add_argument('-fd', '--duration', dest='fragment_duration',
254
- help = 'Fragment duration, in seconds or in the "hh:mm:ss[.xxx]" format',
255
+ help = 'Fragment duration (default is full media length), in seconds or in the "hh:mm:ss[.xxx]" format',
255
256
  type = lambda f: self._is_timedelta(parser, f),
256
257
  default = timedelta(days = 380))
258
+ group.add_argument('-ft', '--trim', dest='fragment_trim',
259
+ help = 'Fragment trimming at the end (optional), in seconds or in the "hh:mm:ss[.xxx]" format',
260
+ type = lambda f: self._is_timedelta(parser, f),
261
+ default = timedelta(0))
257
262
 
258
263
  # Segment
259
264
  segment_parser = subparsers.add_parser(BMFPCommands.SEGMENT,