filter_rename 1.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE +674 -0
- data/README.md +82 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/filter_rename +5 -0
- data/filter_rename.gemspec +44 -0
- data/lib/filter_rename.rb +137 -0
- data/lib/filter_rename.yaml +165 -0
- data/lib/filter_rename/cli.rb +145 -0
- data/lib/filter_rename/config.rb +120 -0
- data/lib/filter_rename/filename.rb +142 -0
- data/lib/filter_rename/filename_factory.rb +36 -0
- data/lib/filter_rename/filetype/image_filename.rb +28 -0
- data/lib/filter_rename/filetype/mp3_filename.rb +82 -0
- data/lib/filter_rename/filetype/pdf_filename.rb +24 -0
- data/lib/filter_rename/filter_base.rb +191 -0
- data/lib/filter_rename/filter_pipe.rb +64 -0
- data/lib/filter_rename/filters.rb +660 -0
- data/lib/filter_rename/utils.rb +283 -0
- data/lib/filter_rename/version.rb +3 -0
- metadata +202 -0
@@ -0,0 +1,283 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module FilterRename
|
4
|
+
|
5
|
+
FILE_SIZES = ['B', 'KB', 'MB', 'GB', 'TB']
|
6
|
+
|
7
|
+
class Boolean; end
|
8
|
+
|
9
|
+
class ::TrueClass
|
10
|
+
def to_boolean
|
11
|
+
self.to_s.to_boolean
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class ::FalseClass
|
16
|
+
def to_boolean
|
17
|
+
self.to_s.to_boolean
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ReadableVariables
|
22
|
+
|
23
|
+
def readonly!
|
24
|
+
@writable = false
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def writable?
|
29
|
+
@writable || @writable == nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ::Integer
|
34
|
+
include ReadableVariables
|
35
|
+
end
|
36
|
+
|
37
|
+
class ::String
|
38
|
+
include ReadableVariables
|
39
|
+
|
40
|
+
def black; "\033[30m#{self}\033[0m" end
|
41
|
+
def red; "\033[31m#{self}\033[0m" end
|
42
|
+
def green; "\033[32m#{self}\033[0m" end
|
43
|
+
def yellow; "\033[33m#{self}\033[0m" end
|
44
|
+
def blue; "\033[34m#{self}\033[0m" end
|
45
|
+
def magenta; "\033[35m#{self}\033[0m" end
|
46
|
+
def cyan; "\033[36m#{self}\033[0m" end
|
47
|
+
def gray; "\033[37m#{self}\033[0m" end
|
48
|
+
def bg_black; "\033[40m#{self}\0330m" end
|
49
|
+
def bg_red; "\033[41m#{self}\033[0m" end
|
50
|
+
def bg_green; "\033[42m#{self}\033[0m" end
|
51
|
+
def bg_brown; "\033[43m#{self}\033[0m" end
|
52
|
+
def bg_blue; "\033[44m#{self}\033[0m" end
|
53
|
+
def bg_magenta; "\033[45m#{self}\033[0m" end
|
54
|
+
def bg_cyan; "\033[46m#{self}\033[0m" end
|
55
|
+
def bg_gray; "\033[47m#{self}\033[0m" end
|
56
|
+
def bold; "\033[1m#{self}\033[22m" end
|
57
|
+
def reverse_color; "\033[7m#{self}\033[27m" end
|
58
|
+
def cr; "\r#{self}" end
|
59
|
+
def clean; "\e[K#{self}" end
|
60
|
+
def new_line; "\n#{self}" end
|
61
|
+
|
62
|
+
def parametrize
|
63
|
+
self.split(/(?<!\\),/).map { |x| x.gsub('\,', ',') }
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_boolean
|
67
|
+
self == 'true'
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_filter
|
71
|
+
Object.const_get("FilterRename::Filters::#{self.to_s.split(/_|-/).map(&:capitalize).join}")
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_switch
|
75
|
+
self.scan(/[A-Z][a-z0-9]*/).map(&:downcase).join '-'
|
76
|
+
end
|
77
|
+
|
78
|
+
def change_date_format(args)
|
79
|
+
format_src = args[:format_src]
|
80
|
+
format_dest = args[:format_dest]
|
81
|
+
short_months = args[:short_months]
|
82
|
+
long_months = args[:long_months]
|
83
|
+
long_days = args[:long_days]
|
84
|
+
short_days = args[:short_days]
|
85
|
+
|
86
|
+
str = self.clone
|
87
|
+
|
88
|
+
regexp = format_src.gsub('<B>', "(#{long_months.join('|')})").gsub('<b>', "(#{short_months.join('|')})")
|
89
|
+
.gsub('<A>', "(#{long_days.join('|')})").gsub('<a>', "(#{short_days.join('|')})")
|
90
|
+
.gsub('<Y>', '[0-9]{4,4}').gsub(/<(d|m|y|H|I|M|S|U)>/, '[0-9]{2,2}')
|
91
|
+
.gsub('<u>', '[0-9]{1,1}')
|
92
|
+
|
93
|
+
to_replace = str.scan(Regexp.new("(#{regexp})", true))
|
94
|
+
|
95
|
+
unless to_replace.empty?
|
96
|
+
to_replace = to_replace.pop
|
97
|
+
template = format_src.gsub(/<([a-zA-Z])>/, '%\1')
|
98
|
+
d = Date.strptime(to_replace[0], template)
|
99
|
+
|
100
|
+
str.gsub! to_replace[0], d.strftime(format_dest.gsub(/<([a-zA-Z])>/, '%\1'))
|
101
|
+
end
|
102
|
+
|
103
|
+
str
|
104
|
+
end
|
105
|
+
|
106
|
+
def map_number_with_index
|
107
|
+
self.gsub(/\d+/).with_index do |num, i|
|
108
|
+
yield num, i
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_number(idx)
|
113
|
+
self.scan(/\d+/)[idx]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
class Messages
|
119
|
+
|
120
|
+
def self.error(e)
|
121
|
+
if e.class == String
|
122
|
+
puts '[E] '.bold.red + e
|
123
|
+
else
|
124
|
+
STDERR.puts 'Error! '.bold.red + e.message
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.warning(m)
|
129
|
+
puts '[W] '.bold.yellow + m
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.ok(m)
|
133
|
+
puts '[V] '.bold.green + m
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.multi(m)
|
137
|
+
puts '[*] '.bold.magenta + m
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.diff(fp)
|
141
|
+
puts fp.diff
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.renamed(fp)
|
145
|
+
if fp.source.full_path != fp.dest.full_path
|
146
|
+
Messages.ok "#{fp.source.filename} #{'>'.bold.green} #{fp.dest.full_filename}"
|
147
|
+
else
|
148
|
+
Messages.ok "#{fp.source.filename} #{'>'.bold.green} #{fp.dest.filename}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.renamed!(old_data, renamed)
|
153
|
+
if old_data[:full_path] != renamed.full_path
|
154
|
+
Messages.ok "#{old_data[:filename]} #{'>'.bold.green} #{renamed.full_filename}"
|
155
|
+
else
|
156
|
+
Messages.ok "#{old_data[:filename]} #{'>'.bold.green} #{renamed.filename}"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
def self.label(text)
|
162
|
+
puts "#{'[/]'.bold.blue} #{text}"
|
163
|
+
end
|
164
|
+
|
165
|
+
def self.skipping(fp)
|
166
|
+
puts '[X] '.bold.yellow + "Skipping <#{fp.source.filename}>, no changes!"
|
167
|
+
end
|
168
|
+
|
169
|
+
def self.changed_tags(fp, old_data = {}, header = true)
|
170
|
+
Messages.ok "<#{fp.source.filename}> tags changed:" if header
|
171
|
+
old_source = old_data.empty? ? fp.source.values : old_data
|
172
|
+
|
173
|
+
fp.dest.values.each do |k, v|
|
174
|
+
puts " #{k}: ".bold.green + (old_source[k] || '-') + ' > '.bold.green + v if ((v != old_source[k]) && (!old_source[k].nil?))
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def self.file_exists(fp)
|
179
|
+
Messages.error "<#{fp.source.filename}> can't be renamed in <#{fp.dest.filename}>, it exists!"
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.short_targets(ff)
|
183
|
+
self.list [ff.targets[:readonly].map { |s| "<#{s.to_s.delete('@')}>"}.join(', ')], :red, '-'
|
184
|
+
self.list [ff.targets[:writable].map { |s| "<#{s.to_s.delete('@')}>"}.join(', ')], :green, '+'
|
185
|
+
puts ''
|
186
|
+
end
|
187
|
+
|
188
|
+
def self.long_targets(ff)
|
189
|
+
self.list ff.targets[:readonly].map { |s| "<#{s.to_s.delete('@')}>" }, :red, '-'
|
190
|
+
self.list ff.targets[:writable].map { |s| "<#{s.to_s.delete('@')}>" }, :green, '+'
|
191
|
+
puts ''
|
192
|
+
end
|
193
|
+
|
194
|
+
def self.item(i, color = :green, ch = '>')
|
195
|
+
puts "[#{ch}] ".bold.send(color) + i
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.list(items, color = :green, ch = '>')
|
199
|
+
items.each { |x| Messages.item(x, color, ch) }
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.config_list(items, color = :green, ch = '>')
|
203
|
+
items.instance_variables.each { |k| Messages.item("#{k.to_s.gsub(/@/, '')}: #{items.instance_variable_get(k)}", color, ch) }
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.config_multilist(items, color = :green, ch = '>')
|
207
|
+
items.instance_variables.each { |k| Messages.item("#{k.to_s.gsub(/@/, '')}: [#{items.instance_variable_get(k).keys.join(', ')}]", color, ch) }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
class UnknownHashCode < StandardError
|
212
|
+
def initialize(hash_type)
|
213
|
+
super "Invalid hash type: #{hash_type}"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
class InvalidMacro < StandardError
|
218
|
+
def initialize(macro)
|
219
|
+
super "Invalid macro: #{macro}"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
class InvalidTarget < StandardError
|
224
|
+
def initialize(target)
|
225
|
+
super "Invalid target: #{target}"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
class InvalidFilterSetting < StandardError
|
230
|
+
def initialize(name)
|
231
|
+
super "Invalid configuration setting: #{name}"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
class InvalidWordsGroup < StandardError
|
236
|
+
def initialize(group)
|
237
|
+
super "Invalid words group: #{group}"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
class InvalidWordsSection < StandardError
|
242
|
+
def initialize(group, section)
|
243
|
+
super "Invalid words section for #{group}: #{section}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
class InvalidWordsIndex < StandardError
|
248
|
+
def initialize(group, section, idx)
|
249
|
+
super "Missing the item #{idx + 1} in #{group}/#{section} words section"
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
class FileNotFound < StandardError
|
254
|
+
def initialize(filename)
|
255
|
+
super "File not found: #{filename}"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
class MissingFiles < StandardError
|
260
|
+
def initialize
|
261
|
+
super 'No filenames specified'
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
class ExistingFile < StandardError
|
266
|
+
def initialize(filename)
|
267
|
+
super "The file #{filename} already exists and won't be overwrite"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
class Interruption < StandardError
|
272
|
+
def initialize
|
273
|
+
super 'Ok ok... Exiting!'
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
Differ.format = :color
|
279
|
+
|
280
|
+
Signal.trap('INT') { raise Interruption }
|
281
|
+
|
282
|
+
Signal.trap('TERM') { raise Interruption }
|
283
|
+
end
|
metadata
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: filter_rename
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Fabio Mucciante
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-03-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '13.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '13.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mp3info
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mimemagic
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: differ
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: exiv2
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: fastimage
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pdf-reader
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: Rename filenames applying a cascade of commands called filters in specified
|
140
|
+
portion of it called targets.
|
141
|
+
email:
|
142
|
+
- fabio.mucciante@gmail.com
|
143
|
+
executables:
|
144
|
+
- filter_rename
|
145
|
+
extensions: []
|
146
|
+
extra_rdoc_files: []
|
147
|
+
files:
|
148
|
+
- ".gitignore"
|
149
|
+
- ".rspec"
|
150
|
+
- ".travis.yml"
|
151
|
+
- CODE_OF_CONDUCT.md
|
152
|
+
- Gemfile
|
153
|
+
- LICENSE
|
154
|
+
- README.md
|
155
|
+
- Rakefile
|
156
|
+
- bin/console
|
157
|
+
- bin/setup
|
158
|
+
- exe/filter_rename
|
159
|
+
- filter_rename.gemspec
|
160
|
+
- lib/filter_rename.rb
|
161
|
+
- lib/filter_rename.yaml
|
162
|
+
- lib/filter_rename/cli.rb
|
163
|
+
- lib/filter_rename/config.rb
|
164
|
+
- lib/filter_rename/filename.rb
|
165
|
+
- lib/filter_rename/filename_factory.rb
|
166
|
+
- lib/filter_rename/filetype/image_filename.rb
|
167
|
+
- lib/filter_rename/filetype/mp3_filename.rb
|
168
|
+
- lib/filter_rename/filetype/pdf_filename.rb
|
169
|
+
- lib/filter_rename/filter_base.rb
|
170
|
+
- lib/filter_rename/filter_pipe.rb
|
171
|
+
- lib/filter_rename/filters.rb
|
172
|
+
- lib/filter_rename/utils.rb
|
173
|
+
- lib/filter_rename/version.rb
|
174
|
+
homepage: https://github.com/fabiomux/filter_rename
|
175
|
+
licenses:
|
176
|
+
- GPL-3.0
|
177
|
+
metadata:
|
178
|
+
bug_tracker_uri: https://github.com/fabiomux/filter_rename/issues
|
179
|
+
documentation_uri: https://www.rubydoc.info/gems/filter_rename/1.0.0
|
180
|
+
homepage_uri: https://github.com/fabiomux/filter_rename
|
181
|
+
source_code_uri: https://github.com/fabiomux/filter_rename
|
182
|
+
wiki_uri: https://github.com/fabiomux/filter_rename/wiki
|
183
|
+
post_install_message:
|
184
|
+
rdoc_options: []
|
185
|
+
require_paths:
|
186
|
+
- lib
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - ">="
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0'
|
192
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
197
|
+
requirements: []
|
198
|
+
rubygems_version: 3.0.8
|
199
|
+
signing_key:
|
200
|
+
specification_version: 4
|
201
|
+
summary: Rename filenames through a chain of filter.
|
202
|
+
test_files: []
|