rename_radically 0.2.0 → 0.3.3
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 +5 -5
- data/bin/rnr +165 -169
- data/lib/rename_radically.rb +241 -417
- metadata +7 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1bc8dcc770e6a9e58d84bd85f9601ec33a4179e551f7ab30361abd6cc7b9e4b8
|
4
|
+
data.tar.gz: 72b9daf2e94ad2a889a2c25bc2304867b5a9e9308ed44714275d9c22d4fb26de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d53ee4b6baa9edc014069cad31cec4e6da06944df8e5d08523ba862ebfa3f92ab0eed25d67903c7abe38e31c1f85161035feb0ae329353153e6a6cea88566faf
|
7
|
+
data.tar.gz: c7f272a9665672d7f2dfa682ee5d5d3c6b16508cba3f2a9bdd01da66f4c7b3b652b4b96418e39be7f815fbf8c1c2bbbc76d8962262ad3823edbe770b834165bf
|
data/bin/rnr
CHANGED
@@ -1,193 +1,189 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'pathname'
|
4
|
+
require 'rename_radically'
|
5
|
+
require 'yaml'
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
|
8
|
+
|
9
|
+
###############################################################################
|
10
|
+
### Helper functions ###
|
11
|
+
###############################################################################
|
12
|
+
|
13
|
+
# Prints out the help reference.
|
14
|
+
def show_help( exit_value )
|
8
15
|
name = "#{File.basename $0}"
|
9
16
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# Widen mode:
|
19
|
-
lines.push "\e[34m#{name} -w/--widen <files>\e[0m: recursively renames " +
|
20
|
-
"the given files and folders adding spaces when needed."
|
21
|
-
# Regex mode:
|
22
|
-
lines.push "\e[34m#{name} -r/--regex <regex> <substitute> <files>\e[0m: " +
|
23
|
-
"recursively renames the given files and folders replacing " +
|
24
|
-
"any match of the given regex with the given substitute."
|
25
|
-
# Renaming script mode:
|
26
|
-
lines.push "\e[34m#{name} -s/--script <files>\e[0m: creates a bash script " +
|
27
|
-
"to quickly rename the given files and folders, for whenever " +
|
28
|
-
"the other modalities cannot yield the desired result."
|
29
|
-
# Help switch:
|
30
|
-
lines.push "\e[34m#{name} -h\e[0m: shows this help reference."
|
31
|
-
# Footer:
|
32
|
-
lines.push ""
|
33
|
-
lines.push "\e[33mNOTE\e[0m: if no files are specified to a command, it " +
|
34
|
-
"will process every file in the current folder."
|
35
|
-
lines.push ""
|
36
|
-
lines.push "See the configuration file located in \e[34m" +
|
37
|
-
"#{ENV['HOME']}/.rnr\e[0m to add your personal tweaks."
|
38
|
-
|
39
|
-
# Max 80 characters per line, but preserving words integrity! :3
|
40
|
-
lines.each do |entry|
|
41
|
-
# 80 characters line container:
|
42
|
-
composed = ""
|
43
|
-
|
44
|
-
# Split each message string on spaces:
|
45
|
-
entry.split( " " ).each do |word|
|
46
|
-
# If the current composed message plus the current word exceeds 80 is
|
47
|
-
# within 80 characters, keep composing:
|
48
|
-
if 80 >= "#{composed + " " + word}".length then
|
49
|
-
# Add a space when needed:
|
50
|
-
unless composed.empty? then
|
51
|
-
composed += " "
|
52
|
-
end
|
53
|
-
composed += "#{word}"
|
54
|
-
|
55
|
-
# If the current word would not fit in an 80 characters line, print the
|
56
|
-
# current composed message, and start composing the next one with an
|
57
|
-
# indentation of 2 spaces.
|
58
|
-
else
|
59
|
-
puts composed
|
60
|
-
composed = " #{word}"
|
61
|
-
end
|
62
|
-
end
|
17
|
+
puts <<-EOF
|
18
|
+
\e[33mReNameRadically: a simple file renamer who mostly hates spaces.\e[0m
|
19
|
+
\e[33mUsage:\e[0m
|
20
|
+
\e[34m#{name} <files>\e[0m: recursively renames the given files and folders to a CamelCase format.
|
21
|
+
\e[34m#{name} -w/--widen <files>\e[0m: recursively renames the given files and folders adding spaces when needed.
|
22
|
+
\e[34m#{name} -r/--regex <regex> <substitute> <files>\e[0m: recursively renames the given files and folders replacing any match of the given regex with the given substitute.
|
23
|
+
\e[34m#{name} -s/--script <files>\e[0m: creates a bash script to quickly rename the given files and folders, for whenever the other modalities cannot yield the desired result.
|
24
|
+
\e[34m#{name} -h\e[0m: shows this help reference.
|
63
25
|
|
64
|
-
|
65
|
-
|
66
|
-
|
26
|
+
\e[33mNOTE\e[0m: if no files are specified to a command, it will process every file in the current folder.
|
27
|
+
|
28
|
+
\e[33mNOTE\e[0m: the whole procedure can be simulated using the --dry-run flag.
|
29
|
+
|
30
|
+
\e[33mNOTE\e[0m: check out the configuration file located in \e[34m~/.config/rnr/config.yml\e[0m to add your personal tweaks.
|
31
|
+
EOF
|
32
|
+
|
33
|
+
exit exit_value.to_i
|
67
34
|
end
|
68
35
|
|
69
|
-
# Here it is! The main protagonist! The Renamer object!
|
70
|
-
rnr = ReNameRadically.new
|
71
36
|
|
72
|
-
# Help reference:
|
73
|
-
if [ "-h", "--help" ].include? ARGV[0] and 1 == ARGV.size then
|
74
|
-
help_reference
|
75
|
-
exit 0
|
76
37
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
tmp.shift
|
81
|
-
tmp.uniq!
|
38
|
+
###############################################################################
|
39
|
+
### Logic entry point ###
|
40
|
+
###############################################################################
|
82
41
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
42
|
+
# Help reference check:
|
43
|
+
if [ '-h', '--help' ].include? ARGV[ 0 ] then
|
44
|
+
show_help 0
|
45
|
+
end
|
87
46
|
|
88
|
-
|
89
|
-
|
90
|
-
|
47
|
+
# Create a config file for the application if it does not already exist:
|
48
|
+
config = Pathname.new "#{ENV[ 'HOME' ]}/.config/rnr/config.yml"
|
49
|
+
unless config.exist? then
|
50
|
+
config.dirname.mkpath
|
51
|
+
config.write <<-EOF
|
52
|
+
# Characters treated as spaces, which get removed while renaming a file in
|
53
|
+
# non-wide mode:
|
54
|
+
:as_spaces:
|
55
|
+
- "_"
|
56
|
+
|
57
|
+
# Characters after which a word should be capitalized in non-wide mode:
|
58
|
+
:delimiters:
|
59
|
+
- "-"
|
60
|
+
- "+"
|
61
|
+
- "("
|
62
|
+
- ")"
|
63
|
+
- "["
|
64
|
+
- "]"
|
65
|
+
- "{"
|
66
|
+
- "}"
|
67
|
+
- "'"
|
68
|
+
- "&"
|
69
|
+
- "."
|
70
|
+
- "!"
|
71
|
+
- "?"
|
72
|
+
|
73
|
+
# Characters after which must not be added a space in wide mode:
|
74
|
+
:ex_after:
|
75
|
+
- "'"
|
76
|
+
- "("
|
77
|
+
- "-"
|
78
|
+
- "<"
|
79
|
+
- "["
|
80
|
+
- "{"
|
81
|
+
- "."
|
82
|
+
|
83
|
+
# Characters before which must not be added a space in wide mode:
|
84
|
+
:ex_before:
|
85
|
+
- "."
|
86
|
+
- ","
|
87
|
+
- "?"
|
88
|
+
- "!"
|
89
|
+
- "'"
|
90
|
+
- ")"
|
91
|
+
- "]"
|
92
|
+
- "}"
|
93
|
+
- ">"
|
94
|
+
- "-"
|
95
|
+
- "_"
|
96
|
+
|
97
|
+
# Name of the script file created by renaming script mode:
|
98
|
+
:script: "REN.bash"
|
99
|
+
|
100
|
+
EOF
|
101
|
+
|
102
|
+
puts "Created a new config file: #{config.realpath}"
|
103
|
+
end
|
91
104
|
|
92
|
-
|
93
|
-
|
105
|
+
# Parse the config:
|
106
|
+
config = YAML.load_file config.to_s
|
107
|
+
|
108
|
+
# Initialize the renamer:
|
109
|
+
rnr = ReNameRadically.new as_spaces: config[ :as_spaces ],
|
110
|
+
delimiters: config[ :delimiters ],
|
111
|
+
ex_after: config[ :ex_after ],
|
112
|
+
ex_before: config[ :ex_before ],
|
113
|
+
script: config[ :script ],
|
114
|
+
dry_run: !ARGV.delete( '--dry-run' ).nil?
|
115
|
+
|
116
|
+
# Check the modality required by the user:
|
117
|
+
modality = :compact
|
118
|
+
r_pattern = ''
|
119
|
+
r_sub = ''
|
120
|
+
if ARGV[ 0 ].to_s[ 0 ] == '-' then
|
121
|
+
case ARGV.shift
|
122
|
+
when '-r', '--regex'
|
123
|
+
if ARGV.size < 2 then
|
124
|
+
show_help -1
|
125
|
+
end
|
126
|
+
modality = :regex
|
127
|
+
r_pattern = ARGV.shift
|
128
|
+
r_sub = ARGV.shift
|
129
|
+
|
130
|
+
when '-s', '--script'
|
131
|
+
modality = :script
|
132
|
+
|
133
|
+
when '-w', '--widen'
|
134
|
+
modality = :widen
|
94
135
|
end
|
136
|
+
end
|
95
137
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
tmp.delete "."
|
112
|
-
tmp.delete ".."
|
113
|
-
|
114
|
-
# This could be quite dangerous if erroneously invoked (eg. in the user's
|
115
|
-
# home directory). Better use a confirmation prompt:
|
116
|
-
print "Do you really want to rename every file and folder in the " +
|
117
|
-
"current directory (#{Dir.pwd})? [y/N] "
|
118
|
-
answer = STDIN.gets.chomp
|
119
|
-
|
120
|
-
# Abort from anything different than y/Y:
|
121
|
-
unless "Y" == Unicode::capitalize( answer ) then
|
122
|
-
puts "Operation aborted."
|
123
|
-
exit 0
|
124
|
-
end
|
125
|
-
|
126
|
-
# User is a moron.
|
127
|
-
elsif 3 > ARGV.size then
|
128
|
-
puts "Must specify at one regex and one substitute for this modality."
|
129
|
-
exit -1
|
138
|
+
# Outcome container:
|
139
|
+
outcome = Hash.new
|
140
|
+
|
141
|
+
# Files to move:
|
142
|
+
files = ARGV
|
143
|
+
|
144
|
+
# If ARGV is empty we gotta make sure the user actually wants to rename
|
145
|
+
# everything in the current folder:
|
146
|
+
if files.empty? then
|
147
|
+
# Ask for confirmation before doing anything:
|
148
|
+
print 'Do you really want to rename every file and folder in the ' \
|
149
|
+
"current directory (#{Dir.pwd})? [y/N] "
|
150
|
+
unless 'Y' == STDIN.gets.chomp.upcase then
|
151
|
+
puts 'Operation aborted.'
|
152
|
+
exit 0
|
130
153
|
end
|
131
154
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
tmp = Dir.entries "."
|
144
|
-
|
145
|
-
# Always remove "." and "..".
|
146
|
-
tmp.delete "."
|
147
|
-
tmp.delete ".."
|
148
|
-
|
149
|
-
# This could be quite dangerous if erroneously invoked (eg. in the user's
|
150
|
-
# home directory). Better use a confirmation prompt:
|
151
|
-
print "Do you really want to rename every file and folder in the " +
|
152
|
-
"current directory (#{Dir.pwd})? [y/N] "
|
153
|
-
answer = STDIN.gets.chomp
|
154
|
-
|
155
|
-
# # Abort from anything different than y/Y:
|
156
|
-
unless "Y" == Unicode::capitalize( answer ) then
|
157
|
-
puts "Operation aborted."
|
158
|
-
exit 0
|
159
|
-
end
|
155
|
+
# If we got here add in every child of the current folder to ARGV:
|
156
|
+
files = Pathname.new( '.' ).children if files.empty?
|
157
|
+
end
|
158
|
+
|
159
|
+
# This one calls a different function than the rest:
|
160
|
+
if modality == :script then
|
161
|
+
outcome = rnr.create_renaming_script files
|
162
|
+
|
163
|
+
if outcome.nil? then
|
164
|
+
puts 'Unable to write the renaming script in the current folder.'
|
165
|
+
exit -2
|
160
166
|
end
|
161
167
|
|
162
|
-
rnr.
|
168
|
+
puts "Created script '#{rnr.script}'."
|
163
169
|
|
164
|
-
#
|
170
|
+
# Everything else is straightforward:
|
165
171
|
else
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
# This could be quite dangerous if erroneously invoked (eg. in the user's
|
179
|
-
# home directory). Better use a confirmation prompt:
|
180
|
-
print "Do you really want to rename every file and folder in the " +
|
181
|
-
"current directory (#{Dir.pwd})? [y/N] "
|
182
|
-
answer = STDIN.gets.chomp
|
183
|
-
|
184
|
-
# Abort from anything different than y/Y:
|
185
|
-
unless "Y" == Unicode::capitalize( answer ) then
|
186
|
-
puts "Operation aborted."
|
187
|
-
exit 0
|
188
|
-
end
|
189
|
-
end
|
172
|
+
# Perform the renaming:
|
173
|
+
outcome = rnr.rename files: files,
|
174
|
+
modality: modality,
|
175
|
+
r_pattern: r_pattern,
|
176
|
+
r_sub: r_sub
|
177
|
+
end
|
178
|
+
|
179
|
+
# Warning about missing files and insufficient permissions:
|
180
|
+
puts 'File(s) not found:' if outcome[ :not_found ].any?
|
181
|
+
outcome[ :not_found ].each do |f|
|
182
|
+
puts " - #{f}"
|
183
|
+
end
|
190
184
|
|
191
|
-
|
185
|
+
puts 'Insufficient permissions to move:' if outcome[ :no_permissions ].any?
|
186
|
+
outcome[ :no_permissions ].each do |f|
|
187
|
+
puts " - #{f}"
|
192
188
|
end
|
193
189
|
|
data/lib/rename_radically.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
|
4
4
|
|
5
5
|
=begin
|
6
6
|
This is the ReNameRadically class.
|
@@ -16,481 +16,305 @@ regex:: replaces all occurrences of the given regex with the given
|
|
16
16
|
renaming script:: creates a bash script to rename files, for whenever the
|
17
17
|
other modalities cannot yield the desired result.
|
18
18
|
=end
|
19
|
-
|
20
19
|
class ReNameRadically
|
21
|
-
@config # Location of the user config file.
|
22
|
-
@as_spaces # Array of characters to be treated as spaces
|
23
|
-
@delimiters # Array of characters to used as word delimiters
|
24
|
-
@ex_after # Array of exceptions not to put a space after in widen mode.
|
25
|
-
@ex_before # Array of exceptions not to put a space before in widen mode.
|
26
|
-
@script # Script name for script renaming mode.
|
27
|
-
|
28
|
-
# Constructor: takes the path of the config file as a parameter, and ensures
|
29
|
-
# it contains the right info. If not, it gets created anew.
|
30
|
-
def initialize( config_file = "#{ENV['HOME']}/.rnr" )
|
31
|
-
@config = Pathname.new config_file
|
32
|
-
|
33
|
-
# Attempt to read from the config file:
|
34
|
-
begin
|
35
|
-
loaded_config = YAML.load_file @config
|
36
|
-
@as_spaces = loaded_config["as_spaces"]
|
37
|
-
@delimiters = loaded_config["delimiters"]
|
38
|
-
@ex_after = loaded_config["ex_after"]
|
39
|
-
@ex_before = loaded_config["ex_before"]
|
40
|
-
@script = loaded_config["script"]
|
41
|
-
|
42
|
-
# Fastest way to check for data consistency:
|
43
|
-
@as_spaces[0]
|
44
|
-
@delimiters[0]
|
45
|
-
@ex_after[0]
|
46
|
-
@ex_before[0]
|
47
|
-
@script = loaded_config["script"][0]
|
48
|
-
|
49
|
-
# If it fails, create a new default config file:
|
50
|
-
rescue
|
51
|
-
# This is the best way I can think of to hardcode the default config file
|
52
|
-
# without breaking the formatting.
|
53
|
-
config = Array.new
|
54
|
-
config.push "# Characters treated as spaces, which get removed while " +
|
55
|
-
"renaming a file in"
|
56
|
-
config.push "# non-wide mode:"
|
57
|
-
config.push "as_spaces:"
|
58
|
-
config.push "- \"_\""
|
59
|
-
config.push " "
|
60
|
-
config.push "# Characters after which a word should be capitalized in" +
|
61
|
-
" non-wide mode:"
|
62
|
-
config.push "delimiters:"
|
63
|
-
config.push "- \"-\""
|
64
|
-
config.push "- \"+\""
|
65
|
-
config.push "- \"(\""
|
66
|
-
config.push "- \")\""
|
67
|
-
config.push "- \"[\""
|
68
|
-
config.push "- \"]\""
|
69
|
-
config.push "- \"{\""
|
70
|
-
config.push "- \"}\""
|
71
|
-
config.push "- \"'\""
|
72
|
-
config.push "- \"&\""
|
73
|
-
config.push "- \".\""
|
74
|
-
config.push "- \"!\""
|
75
|
-
config.push "- \"?\""
|
76
|
-
config.push " "
|
77
|
-
config.push "# Characters after which must not be added a space in " +
|
78
|
-
"wide mode:"
|
79
|
-
config.push "ex_after:"
|
80
|
-
config.push "- \"'\""
|
81
|
-
config.push "- \"(\""
|
82
|
-
config.push "- \"-\""
|
83
|
-
config.push "- \"<\""
|
84
|
-
config.push "- \"[\""
|
85
|
-
config.push "- \"{\""
|
86
|
-
config.push "- \".\""
|
87
|
-
config.push " "
|
88
|
-
config.push "# Characters before which must not be added a space in " +
|
89
|
-
"wide mode:"
|
90
|
-
config.push "ex_before:"
|
91
|
-
config.push "- \".\""
|
92
|
-
config.push "- \",\""
|
93
|
-
config.push "- \"?\""
|
94
|
-
config.push "- \"!\""
|
95
|
-
config.push "- \"'\""
|
96
|
-
config.push "- \")\""
|
97
|
-
config.push "- \"]\""
|
98
|
-
config.push "- \"}\""
|
99
|
-
config.push "- \">\""
|
100
|
-
config.push "- \"-\""
|
101
|
-
config.push "- \"_\""
|
102
|
-
config.push " "
|
103
|
-
config.push "# Name of the script file created by renaming script mode:"
|
104
|
-
config.push "script:"
|
105
|
-
config.push "- \"REN.bash\""
|
106
|
-
config.push " "
|
107
|
-
|
108
|
-
config = config.join "\n"
|
109
|
-
|
110
|
-
loaded_config = YAML.load config
|
111
|
-
|
112
|
-
# Attempt to create the file:
|
113
|
-
begin
|
114
|
-
File.open @config, "w" do |f|
|
115
|
-
f.puts config
|
116
|
-
end
|
117
|
-
puts "Created a new config file: #{@config}"
|
118
|
-
|
119
|
-
# ...And be sure that everything went right:
|
120
|
-
loaded_config = YAML.load_file @config
|
121
|
-
|
122
|
-
# Something went horribly wrong: maybe there's no home folder, or its
|
123
|
-
# permissions are all wrong... So, screw the config file and use default
|
124
|
-
# values for this ride.
|
125
|
-
rescue
|
126
|
-
puts "WARNING: could not read/write file #{@config}, you might want" +
|
127
|
-
" to check out why."
|
128
|
-
end
|
129
20
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
21
|
+
#############################################################################
|
22
|
+
### Attributes ###
|
23
|
+
#############################################################################
|
24
|
+
|
25
|
+
# Dry run flag.
|
26
|
+
attr_reader :dry_run
|
27
|
+
|
28
|
+
# Array of characters to be treated as spaces
|
29
|
+
attr_reader :as_spaces
|
30
|
+
|
31
|
+
# Array of characters to used as word delimiters
|
32
|
+
attr_reader :delimiters
|
33
|
+
|
34
|
+
# Array of exceptions not to put a space after in widen mode.
|
35
|
+
attr_reader :ex_after
|
36
|
+
|
37
|
+
# Array of exceptions not to put a space before in widen mode.
|
38
|
+
attr_reader :ex_before
|
39
|
+
|
40
|
+
# Script name for script renaming mode.
|
41
|
+
attr_reader :script
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
#############################################################################
|
46
|
+
### Public instance methods ###
|
47
|
+
#############################################################################
|
48
|
+
|
49
|
+
# Constructor.
|
50
|
+
# Takes as parameters the config file path and the dry run flag.
|
51
|
+
# Creates the config file if needed.
|
52
|
+
def initialize( dry_run: false,
|
53
|
+
as_spaces: %w[ _ ],
|
54
|
+
delimiters: %w[ - + ( ) [ ] { } ' & . ! ? ],
|
55
|
+
ex_after: %w[ ' ( - < \[ { . ],
|
56
|
+
ex_before: %w[ . , ? ! ' ) \] } > - _ ],
|
57
|
+
script: 'REN.sh'
|
58
|
+
)
|
59
|
+
@dry_run = dry_run
|
60
|
+
@as_spaces = as_spaces
|
61
|
+
@delimiters = delimiters
|
62
|
+
@ex_after = ex_after
|
63
|
+
@ex_before = ex_before
|
64
|
+
@script = script
|
65
|
+
|
66
|
+
# Ensure any invalid values are not used:
|
67
|
+
@as_spaces = Array.new unless @as_spaces.is_a? Array
|
68
|
+
@delimiters = Array.new unless @delimiters.is_a? Array
|
69
|
+
@ex_after = Array.new unless @ex_after.is_a? Array
|
70
|
+
@ex_before = Array.new unless @ex_before.is_a? Array
|
71
|
+
@script = 'REN.sh' if [ '', '.', '..' ].include? @script.to_s
|
137
72
|
end
|
138
73
|
|
139
|
-
# Public method: checks if the given files exist, then prints a list of the
|
140
|
-
# not found ones and returns an array containing the Pathname objects of the
|
141
|
-
# found ones.
|
142
|
-
public
|
143
|
-
def checkFiles( *files )
|
144
|
-
# This will contain the not found files:
|
145
|
-
not_found = Array.new
|
146
74
|
|
147
|
-
# This will contain files we do not have the permissions to move:
|
148
|
-
no_permissions = Array.new
|
149
75
|
|
150
|
-
|
151
|
-
|
76
|
+
# Simple tester function for strings.
|
77
|
+
def tester( text:, modality:, r_pattern: '', r_sub: '' )
|
78
|
+
# Turn this into a pathname:
|
79
|
+
text = Pathname.new text
|
152
80
|
|
153
|
-
|
154
|
-
|
155
|
-
|
81
|
+
return modality_regex text, r_pattern, r_sub if modality == :regex
|
82
|
+
return send( "modality_#{modality}", text ) unless modality == :regex
|
83
|
+
end
|
156
84
|
|
157
|
-
# The file exists!
|
158
|
-
if tmp.exist? and "." != tmp.to_s and ".." != tmp.to_s then
|
159
85
|
|
160
|
-
# And we do have the permissions to move it!
|
161
|
-
if tmp.dirname.writable? then
|
162
|
-
ok.push tmp
|
163
86
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
87
|
+
# Recursively renames the given files using the given modality.
|
88
|
+
# Returns a hash of not found or unchangeable files.
|
89
|
+
def rename( files:, modality:, check_files: true, r_pattern: '', r_sub: '' )
|
90
|
+
# Data to return:
|
91
|
+
ret = Hash.new
|
168
92
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
93
|
+
# If this is true then some extra steps have to be taken:
|
94
|
+
if check_files then
|
95
|
+
ret = check_files files
|
96
|
+
files = ret.delete :ok
|
173
97
|
end
|
174
98
|
|
175
|
-
#
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
puts "- #{entry}"
|
182
|
-
end
|
99
|
+
# Then check each of them
|
100
|
+
files.each do |file|
|
101
|
+
# Special case for regex pattern:
|
102
|
+
if modality == :regex then
|
103
|
+
file = perform_rename file: file,
|
104
|
+
name: modality_regex( file, r_pattern, r_sub )
|
183
105
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
106
|
+
# Rename the file using the right method:
|
107
|
+
else
|
108
|
+
file = perform_rename file: file,
|
109
|
+
name: send( "modality_#{modality}", file )
|
188
110
|
end
|
189
111
|
|
190
|
-
|
112
|
+
# If we just renamed a folder, rename everything within it as well:
|
113
|
+
rename files: file.children,
|
114
|
+
modality: modality,
|
115
|
+
check_files: false,
|
116
|
+
r_pattern: r_pattern,
|
117
|
+
r_sub: r_sub \
|
118
|
+
if file.directory?
|
191
119
|
end
|
192
120
|
|
193
|
-
# Return
|
194
|
-
return
|
121
|
+
# Return what files gave an error:
|
122
|
+
return ret
|
195
123
|
end
|
196
124
|
|
197
|
-
# Public method: will smartly rename a file (Pathname format) to
|
198
|
-
# new_name, preserving the original path and extension. If another file with
|
199
|
-
# the destination name already exists, the new one will have a number
|
200
|
-
# appended to its name. Returns the new name of the file.
|
201
|
-
public
|
202
|
-
def smartRename( file, new_name )
|
203
|
-
# Be sure to remove characters which are not allowed for file names:
|
204
|
-
new_name.gsub! "/" ""
|
205
|
-
new_name.gsub! "\0" ""
|
206
|
-
|
207
|
-
# Also, the max name length is 255, including the extension:
|
208
|
-
new_name.scan( /.{#{255 - "#{file.extname}".length}}/ )[0]
|
209
|
-
|
210
|
-
# Hopefully, this is already the name that will be used:
|
211
|
-
destination = Pathname.new "#{file.dirname}/#{new_name}#{file.extname}"
|
212
|
-
|
213
|
-
# Rename the file only if the destination is different than the origin and
|
214
|
-
# if the file name is not empty.
|
215
|
-
unless file.basename == destination.basename or "#{new_name}".empty? or
|
216
|
-
"." == new_name or ".." == new_name then
|
217
|
-
# Index variable for worst-case scenario:
|
218
|
-
index = 0
|
219
|
-
|
220
|
-
# To be honest... If this goes beyond 2, the user is really just messing
|
221
|
-
# with us.
|
222
|
-
while destination.exist? do
|
223
|
-
index += 1
|
224
|
-
destination = Pathname.new "#{file.dirname}/#{new_name}-#{index}" +
|
225
|
-
"#{file.extname}"
|
226
|
-
end
|
227
|
-
|
228
|
-
# Rename away!
|
229
|
-
file.rename destination
|
230
|
-
end
|
231
125
|
|
232
|
-
# In any case, return the destination (Pathname format):
|
233
|
-
return destination
|
234
|
-
end
|
235
126
|
|
236
|
-
#
|
237
|
-
#
|
238
|
-
#
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
file_name = file.basename( file.extname ).to_s
|
243
|
-
|
244
|
-
# Replace the characters contained in the "as_spaces" field in the config
|
245
|
-
# file with spaces:
|
246
|
-
@as_spaces.each do |remove|
|
247
|
-
file_name.gsub! remove, " "
|
248
|
-
end
|
127
|
+
# Creates a bash script to rename files.
|
128
|
+
# Returns nil if the file cannot be created in the current folder.
|
129
|
+
# Otherwise returns a hash of not found or unchangeable files.
|
130
|
+
def create_renaming_script( files )
|
131
|
+
# Check for permissions first:
|
132
|
+
return nil unless Pathname.new( '.' ).dirname.writable?
|
249
133
|
|
250
|
-
#
|
251
|
-
|
252
|
-
file_name.gsub! delimiter, "#{delimiter} "
|
253
|
-
end
|
134
|
+
# Sanitize files first:
|
135
|
+
files = check_files files
|
254
136
|
|
255
|
-
#
|
256
|
-
|
137
|
+
# Write the file:
|
138
|
+
File.open @script, 'w' do |f|
|
139
|
+
# Write the header and make it executable:
|
140
|
+
f.puts "#! /usr/bin/env bash\n\n"
|
141
|
+
f.chmod 0700
|
257
142
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
end
|
262
|
-
|
263
|
-
# Rename the file and return its new name:
|
264
|
-
return smartRename file, file_name.join
|
265
|
-
end
|
266
|
-
|
267
|
-
# Private method, called through compact: recursively renames a folder and
|
268
|
-
# its content to a compact CamelCase version.
|
269
|
-
private
|
270
|
-
def compactFolder( folder )
|
271
|
-
# Rename the folder:
|
272
|
-
new_folder_name = compactFile folder
|
273
|
-
|
274
|
-
# Then rename everything it contains, recursively:
|
275
|
-
new_folder_name.entries.each do |entry|
|
276
|
-
# Ignore "." and "..", though.
|
277
|
-
if "." != entry.to_s and ".." != entry.to_s then
|
278
|
-
compact Pathname.new "#{new_folder_name.realpath}/#{entry}"
|
143
|
+
# Write in each file:
|
144
|
+
files.delete( :ok ).map do |file|
|
145
|
+
f.puts "mv '#{file}' \\\n '#{file}'\n\n"
|
279
146
|
end
|
147
|
+
|
148
|
+
# As a last thing add in the self-destruction line:
|
149
|
+
f.puts "# Self-destruction line, you may not want to edit this:\n" \
|
150
|
+
"rm '#{@script}'\n\n"
|
280
151
|
end
|
152
|
+
|
153
|
+
# Return what files gave an error:
|
154
|
+
return files
|
281
155
|
end
|
282
156
|
|
283
|
-
# Public method: checks if the given files exist via checkFiles, then calls
|
284
|
-
# compactFile and compactFolder to process respectedly the given files and
|
285
|
-
# folders.
|
286
|
-
public
|
287
|
-
def compact( *files )
|
288
|
-
# First off: check if the files exist.
|
289
|
-
existing = checkFiles *files
|
290
157
|
|
291
|
-
# Behave differently for files and folders:
|
292
|
-
existing.each do |entry|
|
293
|
-
# Folders:
|
294
|
-
if entry.directory? then
|
295
|
-
compactFolder entry
|
296
158
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
end
|
301
|
-
end
|
302
|
-
end
|
159
|
+
#############################################################################
|
160
|
+
### Private instance methods ###
|
161
|
+
#############################################################################
|
303
162
|
|
304
|
-
# Private method, called through widen: renames a single file to a wide
|
305
|
-
# version. This contains the main logic of renaming files in such way.
|
306
|
-
# Returns the new name of the renamed file.
|
307
163
|
private
|
308
|
-
def widenFile( file )
|
309
|
-
# Put the file's basename into an array, without its extension:
|
310
|
-
file_name = file.basename( file.extname ).to_s
|
311
|
-
|
312
|
-
# This will be the file's new name:
|
313
|
-
new_file_name = ""
|
314
|
-
|
315
|
-
# Read the file name character by character:
|
316
|
-
file_name.chars.each do |c|
|
317
|
-
# To avoid useless spaces, these rules must be respected to add a space
|
318
|
-
# before the current character:
|
319
|
-
# 1. c must not be a space.
|
320
|
-
# 2. new_file_name must not be empty
|
321
|
-
# 3. new_file_name[-1] must not be a space
|
322
|
-
# 4. c must not be included in @ex_before
|
323
|
-
# 5. new_file_name[-1] must not be included in @ex_after
|
324
|
-
# 6. c and new_file_name[-1] must not both be numbers
|
325
|
-
# 6. c must be equal to Unicode::capitalize c
|
326
|
-
if c != " " and false == new_file_name.empty? and
|
327
|
-
" " != new_file_name[-1] and false == ( @ex_before.include? c ) and
|
328
|
-
false == ( @ex_after.include? new_file_name[-1] ) and
|
329
|
-
( nil == ( c =~ /[0-9]/ ) or
|
330
|
-
nil == ( new_file_name[-1] =~ /[0-9]/ )
|
331
|
-
) and c == Unicode.capitalize( c ) then
|
332
|
-
new_file_name += " "
|
333
|
-
end
|
334
164
|
|
335
|
-
|
336
|
-
|
165
|
+
# Renames a file, taking @dry_run into account.
|
166
|
+
# Takes as parameters a Pathname and a new name.
|
167
|
+
# The original file's extension is preserved.
|
168
|
+
# If a file with the new name already exists, appends a number to it.
|
169
|
+
# Returns the new file's pathname.
|
170
|
+
def perform_rename( file:, name:, counter: nil )
|
171
|
+
# Remove unwanted characters:
|
172
|
+
name.gsub!( /(\/|\0)/, "" )
|
173
|
+
|
174
|
+
# Add an underscore to the counter:
|
175
|
+
counter = "_#{counter}" unless counter.nil?
|
176
|
+
|
177
|
+
# Also the single file name is 255 characters, including the extension:
|
178
|
+
name = name[ 0..(255 - file.extname.length - counter.to_s.length) ]
|
179
|
+
|
180
|
+
# Compose the final name:
|
181
|
+
destination = Pathname.new "#{file.dirname}/" \
|
182
|
+
"#{name}#{counter}#{file.extname}"
|
183
|
+
|
184
|
+
# Only rename the file if:
|
185
|
+
# - the new name isn't '.' or '..'
|
186
|
+
# - the name isn't empty
|
187
|
+
# - the new name is different than the old one
|
188
|
+
if !name.match( /^\.{1,2}$/ ) and
|
189
|
+
!name.empty? and
|
190
|
+
file.basename != destination.basename
|
191
|
+
then
|
192
|
+
# If the destination already exist try again incrementing the counter:
|
193
|
+
if destination.exist? then
|
194
|
+
destination = perform_rename file: file,
|
195
|
+
name: name,
|
196
|
+
counter: (counter.to_s[ 1.. ].to_i + 1)
|
197
|
+
|
198
|
+
# If it's a dry run, simply print a log:
|
199
|
+
elsif @dry_run then
|
200
|
+
puts "DRY RUN: #{file} => #{destination}"
|
201
|
+
destination = file
|
202
|
+
|
203
|
+
# Otherwise, rename:
|
204
|
+
else
|
205
|
+
file.rename destination
|
206
|
+
end
|
337
207
|
end
|
338
208
|
|
339
|
-
#
|
340
|
-
return
|
209
|
+
# Always return the destination:
|
210
|
+
return destination
|
341
211
|
end
|
342
212
|
|
343
|
-
# Private method, called through widen: recursively renames a folder and
|
344
|
-
# its content to a wide name.
|
345
|
-
private
|
346
|
-
def widenFolder( folder )
|
347
|
-
# Rename the folder:
|
348
|
-
new_folder_name = widenFile folder
|
349
|
-
|
350
|
-
# Then rename everything it contains, recursively:
|
351
|
-
new_folder_name.entries.each do |entry|
|
352
|
-
# Ignore "." and "..", though.
|
353
|
-
if "." != entry.to_s and ".." != entry.to_s then
|
354
|
-
widen Pathname.new "#{new_folder_name.realpath}/#{entry}"
|
355
|
-
end
|
356
|
-
end
|
357
|
-
end
|
358
213
|
|
359
|
-
|
360
|
-
#
|
361
|
-
#
|
214
|
+
|
215
|
+
# Checks if the given file names exist, prints a list of those not existing
|
216
|
+
# and without write permissions, then returns an array of pathnames of the
|
217
|
+
# rest.
|
362
218
|
public
|
363
|
-
def
|
364
|
-
#
|
365
|
-
|
219
|
+
def check_files( files )
|
220
|
+
# Containers:
|
221
|
+
not_found = Array.new
|
222
|
+
no_permissions = Array.new
|
223
|
+
ok = Array.new
|
224
|
+
|
225
|
+
# Check each file:
|
226
|
+
files.uniq.sort_by { |e| e.to_s.downcase }.each do |file|
|
227
|
+
# Turn it into a pathname:
|
228
|
+
file = Pathname.new file.to_s
|
366
229
|
|
367
|
-
|
368
|
-
|
369
|
-
# Folders:
|
370
|
-
if entry.directory? then
|
371
|
-
widenFolder entry
|
230
|
+
# Ignore these:
|
231
|
+
next if file.basename.to_s.match( /^\.{1,2}$/ )
|
372
232
|
|
373
|
-
#
|
233
|
+
# Check where it belongs:
|
234
|
+
if !file.exist? then
|
235
|
+
not_found << file
|
236
|
+
elsif !file.writable? or !file.dirname.writable? then
|
237
|
+
no_permissions << file
|
374
238
|
else
|
375
|
-
|
239
|
+
ok << file
|
376
240
|
end
|
377
241
|
end
|
242
|
+
|
243
|
+
# Return only the valid files:
|
244
|
+
return { ok: ok, not_found: not_found, no_permissions: no_permissions }
|
378
245
|
end
|
379
246
|
|
380
|
-
# Private method, called through regexRename: renames a single file using a
|
381
|
-
# given regex. This contains the main logic of renaming files in such way.
|
382
|
-
# Returns the new name of the renamed file.
|
383
|
-
private
|
384
|
-
def regexRenameFile( file, regex, with )
|
385
|
-
# Get the file's basename, without its extension:
|
386
|
-
file_name = file.basename( file.extname ).to_s
|
387
247
|
|
388
|
-
# Apply the regex!
|
389
|
-
file_name.gsub! regex, "#{with}"
|
390
248
|
|
391
|
-
|
392
|
-
|
393
|
-
end
|
249
|
+
### Renaming modalities
|
250
|
+
#############################################################################
|
394
251
|
|
395
|
-
#
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
252
|
+
# Generates a compacted file name for the given pathname.
|
253
|
+
def modality_compact( file )
|
254
|
+
# Take in the original file's name:
|
255
|
+
name = file.basename( file.extname ).to_s
|
256
|
+
# Turn these into spaces:
|
257
|
+
.gsub( /(#{@as_spaces.map { |a| Regexp.escape a }.join '|'})/, ' ' )
|
258
|
+
# Add spaces after these:
|
259
|
+
.gsub( /(#{@delimiters.map { |a| Regexp.escape a }.join '|'})/, '\1 ' )
|
260
|
+
# Split it on spaces:
|
261
|
+
.split ' '
|
262
|
+
|
263
|
+
# Do the capitalization:
|
264
|
+
name.each_with_index do |word, idx|
|
265
|
+
# Ignore roman numbers:
|
266
|
+
name[ idx ] = word.capitalize unless word.match( /^[IVXLCDM]+$/ )
|
267
|
+
name[ idx ] = word.upcase if word.match( /^[ivxlcdm]+$/ )
|
409
268
|
end
|
269
|
+
|
270
|
+
# Return the joined name:
|
271
|
+
return name.join
|
410
272
|
end
|
411
273
|
|
412
|
-
# Public method: checks if the given files exist via checkFiles, then calls
|
413
|
-
# regexRenameFile and regexRenameFolder to process respectedly the given
|
414
|
-
# files and folders.
|
415
|
-
public
|
416
|
-
def regexRename( *files, regex, with )
|
417
|
-
# First off: check if the files exist.
|
418
|
-
existing = checkFiles *files
|
419
274
|
|
420
|
-
# Behave differently for files and folders:
|
421
|
-
existing.each do |entry|
|
422
|
-
# Folders:
|
423
|
-
if entry.directory? then
|
424
|
-
regexRenameFolder entry, regex, "#{with}"
|
425
275
|
|
426
|
-
|
427
|
-
|
428
|
-
|
276
|
+
# Generates a widened file name for the given pathname.
|
277
|
+
def modality_widen( file )
|
278
|
+
# This starts off empty:
|
279
|
+
name = ''
|
280
|
+
|
281
|
+
# Let's parse each character:
|
282
|
+
file.basename( file.extname ).to_s.chars.each do |c|
|
283
|
+
# To avoid extra spaces we have to follow these rules:
|
284
|
+
# 1. c must not be a space
|
285
|
+
# 2. name must not be empty
|
286
|
+
# 3. name[ -1 ] must not be a space
|
287
|
+
# 4. c must not be included in @ex_before
|
288
|
+
# 5. name[ -1 ] must not be included in @ex_after
|
289
|
+
# 6. c and name[ -1 ] must not both be numbers
|
290
|
+
# 7. c must be equal to c.upcase
|
291
|
+
# 8. c and name[ -1 ] must not be roman numbers
|
292
|
+
if c != ' ' and
|
293
|
+
!name.empty? and
|
294
|
+
name[ -1 ] != ' ' and
|
295
|
+
!@ex_before.include? c and
|
296
|
+
!@ex_after.include? name[ -1 ] and
|
297
|
+
!( c.match( /[0-9]/ ) and name[ -1 ].match( /[0-9]/ ) ) and
|
298
|
+
c == c.upcase and
|
299
|
+
!( c.match( /[IVXLCDM]/ ) and name[ -1 ].match( /[IVXLCDM]/ ) )
|
300
|
+
then
|
301
|
+
name += ' '
|
429
302
|
end
|
430
|
-
end
|
431
|
-
end
|
432
303
|
|
433
|
-
|
434
|
-
|
435
|
-
# checkFiles, then creates a bash script to easily rename them.
|
436
|
-
public
|
437
|
-
def createScript( *files )
|
438
|
-
# Pointless to go any further if the current directory is not writable:
|
439
|
-
unless Pathname.new( "." ).dirname.writable? then
|
440
|
-
puts "You do not have the permissions to create a file in this folder."
|
441
|
-
exit -1
|
304
|
+
# Always add in the character:
|
305
|
+
name += c
|
442
306
|
end
|
443
307
|
|
444
|
-
#
|
445
|
-
|
446
|
-
|
447
|
-
# Now, gotta be sure that @script is not in the list of the files that
|
448
|
-
# should be renamed:
|
449
|
-
existing.delete Pathname.new @script
|
450
|
-
|
451
|
-
# Just to be 100% sure:
|
452
|
-
begin
|
453
|
-
existing.each_with_index do |entry, idx|
|
454
|
-
# Only the first time: create the script.
|
455
|
-
if 0 == idx then
|
456
|
-
File.open @script, "w" do |f|
|
457
|
-
# Script header:
|
458
|
-
f.puts "#!/usr/bin/env bash"
|
459
|
-
f.puts ""
|
460
|
-
|
461
|
-
# Make it executable:
|
462
|
-
f.chmod 0700
|
463
|
-
end
|
464
|
-
end
|
465
|
-
|
466
|
-
# Append the line to rename the current file:
|
467
|
-
File.open @script, "a" do |f|
|
468
|
-
f.puts "mv \"#{entry}\" \\"
|
469
|
-
f.puts " \"#{entry}\""
|
470
|
-
f.puts ""
|
471
|
-
end
|
472
|
-
|
473
|
-
# Only the last time: add the last touches to the script.
|
474
|
-
if idx == existing.size - 1 then
|
475
|
-
File.open @script, "a" do |f|
|
476
|
-
# Self destruct line:
|
477
|
-
f.puts "# Self-destruction line, you may not want to edit this:"
|
478
|
-
f.puts "rm \"#{@script}\""
|
479
|
-
|
480
|
-
# And an empty line at the end, because I'm that kind of guy.
|
481
|
-
f.puts ""
|
482
|
-
end
|
483
|
-
end
|
484
|
-
end
|
308
|
+
# Return the composed name:
|
309
|
+
return name
|
310
|
+
end
|
485
311
|
|
486
|
-
# A little something for the user:
|
487
|
-
puts "Created script file: #{@script}"
|
488
312
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
313
|
+
|
314
|
+
# Generates a new file name for the given pathname using the given regex
|
315
|
+
# pattern and sub value.
|
316
|
+
def modality_regex( file, pattern, sub )
|
317
|
+
return file.basename( file.extname ).to_s.gsub( /#{pattern}/, sub.to_s )
|
494
318
|
end
|
495
319
|
|
496
320
|
end
|
metadata
CHANGED
@@ -1,35 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rename_radically
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maurizio Oliveri
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: unicode
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0.4'
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 0.4.4.2
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0.4'
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 0.4.4.2
|
11
|
+
date: 2022-05-06 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
33
13
|
description: A simple (and probably dirty) files mass-renamer.
|
34
14
|
email:
|
35
15
|
- 6tsukiyami9@gmail.com
|
@@ -44,7 +24,7 @@ homepage: https://github.com/Soulsuke/ReNameR
|
|
44
24
|
licenses:
|
45
25
|
- GPL-3.0
|
46
26
|
metadata: {}
|
47
|
-
post_install_message:
|
27
|
+
post_install_message:
|
48
28
|
rdoc_options: []
|
49
29
|
require_paths:
|
50
30
|
- lib
|
@@ -59,9 +39,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
39
|
- !ruby/object:Gem::Version
|
60
40
|
version: '0'
|
61
41
|
requirements: []
|
62
|
-
|
63
|
-
|
64
|
-
signing_key:
|
42
|
+
rubygems_version: 3.3.7
|
43
|
+
signing_key:
|
65
44
|
specification_version: 4
|
66
45
|
summary: ReNameRadically
|
67
46
|
test_files: []
|