rfs 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +7 -0
- data/Rakefile.rb +193 -0
- data/bin/RenameFileSet.rbw +14 -0
- data/bin/rfs.rb +214 -0
- data/bin/rfsd.rb +8 -0
- data/description.txt +24 -0
- data/lib/RenameFileSet.bak.rb +372 -0
- data/lib/errors.rb +15 -0
- data/lib/filters.rb +68 -0
- data/lib/gui.rb +216 -0
- data/lib/innate/array.rb +104 -0
- data/lib/innate/coverage.rb +315 -0
- data/lib/innate/debug.rb +12 -0
- data/lib/innate/debugger.rb +944 -0
- data/lib/innate/file.rb +5 -0
- data/lib/innate/filelines.rb +148 -0
- data/lib/innate/kernel.rb +41 -0
- data/lib/innate/metaid.rb +30 -0
- data/lib/innate/mkdirs.rb +12 -0
- data/lib/innate/regexp.rb +80 -0
- data/lib/innate/reload.rb +11 -0
- data/lib/innate/roman.rb +72 -0
- data/lib/innate/scriptlines.rb +60 -0
- data/lib/innate/string.rb +56 -0
- data/lib/innate/test/all_tests.rb +11 -0
- data/lib/innate/test/files/mkdirs_dummy.file +1 -0
- data/lib/innate/test/files/reloadtarget.rb +5 -0
- data/lib/innate/test/files/reloadtarget1.rb +5 -0
- data/lib/innate/test/files/reloadtarget2.rb +5 -0
- data/lib/innate/test/test_coverage.rb +13 -0
- data/lib/innate/test/testarray.rb +98 -0
- data/lib/innate/test/testfile.rb +15 -0
- data/lib/innate/test/testfilelines.rb +106 -0
- data/lib/innate/test/testkernel.rb +30 -0
- data/lib/innate/test/testmkdirs.rb +19 -0
- data/lib/innate/test/testregexp.rb +86 -0
- data/lib/innate/test/testreload.rb +61 -0
- data/lib/innate/test/testroman.rb +54 -0
- data/lib/innate/test/testscriptlines.rb +39 -0
- data/lib/innate/test/teststring.rb +52 -0
- data/lib/innate/test/testtitlecase.rb +20 -0
- data/lib/innate/titlecase.rb +64 -0
- data/lib/innate/tracerequire.rb +22 -0
- data/lib/namesource.rb +53 -0
- data/lib/options.rb +64 -0
- data/lib/providers.rb +93 -0
- data/lib/regexp.rb +56 -0
- data/lib/rename_functions.rb +142 -0
- data/lib/renamer.rb +210 -0
- data/lib/results.rb +83 -0
- data/lib/test/test_helper.rb +147 -0
- data/tests/dir/file1 +0 -0
- data/tests/dir/file2 +0 -0
- data/tests/dir/file3 +0 -0
- data/tests/test_helper.rb +147 -0
- data/tests/test_rename_functions.rb +605 -0
- metadata +105 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2005 Darrick Wiebe
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rake/contrib/rubyforgepublisher'
|
5
|
+
|
6
|
+
PKG_NAME = 'rfs'
|
7
|
+
PKG_VERSION = '0.1'
|
8
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
9
|
+
|
10
|
+
RELEASE_NAME = "REL #{PKG_VERSION}"
|
11
|
+
|
12
|
+
RUBY_FORGE_PROJECT = "rfs"
|
13
|
+
RUBY_FORGE_USER = "pangloss"
|
14
|
+
|
15
|
+
task :default => :test
|
16
|
+
Rake::TestTask.new { |t|
|
17
|
+
t.pattern = 'tests/test_rename_functions.rb'
|
18
|
+
}
|
19
|
+
|
20
|
+
# Create compressed packages
|
21
|
+
dist_dirs = [ "lib", "tests"]
|
22
|
+
|
23
|
+
# Genereate the RDoc documentation
|
24
|
+
|
25
|
+
#Rake::RDocTask.new { |rdoc|
|
26
|
+
#rdoc.rdoc_dir = 'doc'
|
27
|
+
#rdoc.title = "Rename File Set"
|
28
|
+
#rdoc.options << '--line-numbers --inline-source --main README'
|
29
|
+
#rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
30
|
+
#rdoc.rdoc_files.include('README', 'CHANGELOG', 'MIT-LICENSE', 'DESCRIPTION')
|
31
|
+
#rdoc.rdoc_files.include('lib/*.rb')
|
32
|
+
#}
|
33
|
+
|
34
|
+
spec = Gem::Specification.new do |s|
|
35
|
+
s.name = PKG_NAME
|
36
|
+
s.version = PKG_VERSION
|
37
|
+
s.summary = "A utility that allows you to use regular expressions to manage large sets of files or folders."
|
38
|
+
s.description = <<-EOD
|
39
|
+
Rename File Set is a powerful way to manage large or small
|
40
|
+
sets of files such as mp3 collections etc. It uses the full
|
41
|
+
power of regular expressions in at least a dozen useful
|
42
|
+
operations. Fox GUI or command-line.
|
43
|
+
EOD
|
44
|
+
|
45
|
+
s.files = (Dir.glob( "./**/*" ) #+
|
46
|
+
#Dir.glob( "./**/innate/**/*")
|
47
|
+
).delete_if { |item| item.include?( "\.svn" ) || item.include?("\pkg") }
|
48
|
+
s.require_path = 'lib'
|
49
|
+
s.has_rdoc = false
|
50
|
+
# s.test_files = ['./tests/test_rename_functions.rb', './lib/innate/test/all_tests.rb']
|
51
|
+
|
52
|
+
s.bindir = 'bin'
|
53
|
+
s.executables << 'rfs.rb'
|
54
|
+
s.executables << 'rfsd.rb'
|
55
|
+
s.executables << 'RenameFileSet.rbw'
|
56
|
+
|
57
|
+
s.author = "Darrick Wiebe"
|
58
|
+
s.email = "darrick@innatesoftware.com"
|
59
|
+
s.homepage = "http://rfs.rubyforge.org"
|
60
|
+
s.rubyforge_project = "rfs"
|
61
|
+
end
|
62
|
+
|
63
|
+
Rake::GemPackageTask.new(spec) do |p|
|
64
|
+
p.gem_spec = spec
|
65
|
+
p.need_tar = true
|
66
|
+
# p.need_zip = true
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "Publish the beta gem"
|
70
|
+
task :pgem => [:package] do
|
71
|
+
Rake::SshFilePublisher.new("pangloss@rfs.rubyforge.org", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
|
72
|
+
#`ssh davidhh@wrath.rubyonrails.com './gemupdate.sh'`
|
73
|
+
end
|
74
|
+
|
75
|
+
desc "Publish the API documentation"
|
76
|
+
task :pdoc => [:rdoc] do
|
77
|
+
Rake::SshDirPublisher.new("davidhh@wrath.rubyonrails.com", "public_html/as", "doc").upload
|
78
|
+
end
|
79
|
+
|
80
|
+
desc "Publish the release files to RubyForge."
|
81
|
+
task :release => [:package] do
|
82
|
+
files = ["gem", "tgz", "zip"].map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
|
83
|
+
|
84
|
+
if RUBY_FORGE_PROJECT then
|
85
|
+
require 'net/http'
|
86
|
+
require 'open-uri'
|
87
|
+
|
88
|
+
project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
|
89
|
+
project_data = open(project_uri) { |data| data.read }
|
90
|
+
group_id = project_data[/[?&]group_id=(\d+)/, 1]
|
91
|
+
raise "Couldn't get group id" unless group_id
|
92
|
+
|
93
|
+
# This echos password to shell which is a bit sucky
|
94
|
+
if ENV["RUBY_FORGE_PASSWORD"]
|
95
|
+
password = ENV["RUBY_FORGE_PASSWORD"]
|
96
|
+
else
|
97
|
+
print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
|
98
|
+
password = STDIN.gets.chomp
|
99
|
+
end
|
100
|
+
|
101
|
+
login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
102
|
+
data = [
|
103
|
+
"login=1",
|
104
|
+
"form_loginname=#{RUBY_FORGE_USER}",
|
105
|
+
"form_pw=#{password}"
|
106
|
+
].join("&")
|
107
|
+
http.post("/account/login.php", data)
|
108
|
+
end
|
109
|
+
|
110
|
+
cookie = login_response["set-cookie"]
|
111
|
+
raise "Login failed" unless cookie
|
112
|
+
headers = { "Cookie" => cookie }
|
113
|
+
|
114
|
+
release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
|
115
|
+
release_data = open(release_uri, headers) { |data| data.read }
|
116
|
+
package_id = release_data[/[?&]package_id=(\d+)/, 1]
|
117
|
+
raise "Couldn't get package id" unless package_id
|
118
|
+
|
119
|
+
first_file = true
|
120
|
+
release_id = ""
|
121
|
+
|
122
|
+
files.each do |filename|
|
123
|
+
basename = File.basename(filename)
|
124
|
+
file_ext = File.extname(filename)
|
125
|
+
file_data = File.open(filename, "rb") { |file| file.read }
|
126
|
+
|
127
|
+
puts "Releasing #{basename}..."
|
128
|
+
|
129
|
+
release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
|
130
|
+
release_date = Time.now.strftime("%Y-%m-%d %H:%M")
|
131
|
+
type_map = {
|
132
|
+
".zip" => "3000",
|
133
|
+
".tgz" => "3110",
|
134
|
+
".gz" => "3110",
|
135
|
+
".gem" => "1400"
|
136
|
+
}; type_map.default = "9999"
|
137
|
+
type = type_map[file_ext]
|
138
|
+
boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
|
139
|
+
|
140
|
+
query_hash = if first_file then
|
141
|
+
{
|
142
|
+
"group_id" => group_id,
|
143
|
+
"package_id" => package_id,
|
144
|
+
"release_name" => RELEASE_NAME,
|
145
|
+
"release_date" => release_date,
|
146
|
+
"type_id" => type,
|
147
|
+
"processor_id" => "8000", # Any
|
148
|
+
"release_notes" => "",
|
149
|
+
"release_changes" => "",
|
150
|
+
"preformatted" => "1",
|
151
|
+
"submit" => "1"
|
152
|
+
}
|
153
|
+
else
|
154
|
+
{
|
155
|
+
"group_id" => group_id,
|
156
|
+
"release_id" => release_id,
|
157
|
+
"package_id" => package_id,
|
158
|
+
"step2" => "1",
|
159
|
+
"type_id" => type,
|
160
|
+
"processor_id" => "8000", # Any
|
161
|
+
"submit" => "Add This File"
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
165
|
+
query = "?" + query_hash.map do |(name, value)|
|
166
|
+
[name, URI.encode(value)].join("=")
|
167
|
+
end.join("&")
|
168
|
+
|
169
|
+
data = [
|
170
|
+
"--" + boundary,
|
171
|
+
"Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
|
172
|
+
"Content-Type: application/octet-stream",
|
173
|
+
"Content-Transfer-Encoding: binary",
|
174
|
+
"", file_data, ""
|
175
|
+
].join("\x0D\x0A")
|
176
|
+
|
177
|
+
release_headers = headers.merge(
|
178
|
+
"Content-Type" => "multipart/form-data; boundary=#{boundary}"
|
179
|
+
)
|
180
|
+
|
181
|
+
target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
|
182
|
+
http.post(target + query, data, release_headers)
|
183
|
+
end
|
184
|
+
|
185
|
+
if first_file then
|
186
|
+
release_id = release_response.body[/release_id=(\d+)/, 1]
|
187
|
+
raise("Couldn't get release id") unless release_id
|
188
|
+
end
|
189
|
+
|
190
|
+
first_file = false
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
$:.unshift File.join(File.split(__FILE__).first, '../lib')
|
2
|
+
require 'gui'
|
3
|
+
require 'renamer'
|
4
|
+
|
5
|
+
|
6
|
+
if $0 == __FILE__
|
7
|
+
$>.sync = true
|
8
|
+
theApp = FXApp.new
|
9
|
+
theMainWindow = RenameWindow.new theApp
|
10
|
+
theMainWindow.renamer = Renamer.new
|
11
|
+
theApp.create
|
12
|
+
theMainWindow.show
|
13
|
+
theApp.run
|
14
|
+
end
|
data/bin/rfs.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
$:.unshift File.expand_path(File.join(File.split(__FILE__).first, '../lib'))
|
3
|
+
require 'renamer'
|
4
|
+
require 'optparse'
|
5
|
+
require 'results'
|
6
|
+
|
7
|
+
class CommandLineInterface
|
8
|
+
def self.confirm
|
9
|
+
@@options[:confirm] = proc do |path, oldfn, newfn, full_name, exists, default|
|
10
|
+
r = %w{Yes All No Cancel}
|
11
|
+
begin
|
12
|
+
print "\"#{File.join path, oldfn}\" =>#{exists ? ' existing file' : ''} \"#{newfn}\"? [#{r.join '/'}] " + (default ? "(#{default}) " : '')
|
13
|
+
s = (i = STDIN.gets).prefix_to_i?(*r)
|
14
|
+
end until s or (i == "\n" and default)
|
15
|
+
s ? s.downcase.to_sym : default
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.noconfirm
|
20
|
+
@@options[:confirm] = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.output(*a)
|
24
|
+
@@results.output(*a)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.start
|
28
|
+
op = OptionParser.new
|
29
|
+
file_provider = Provider::File::NonRecursive
|
30
|
+
@@options = options = {}
|
31
|
+
@@results = CollectResults.new $>
|
32
|
+
renamer = Renamer.new
|
33
|
+
|
34
|
+
# basic default settings.
|
35
|
+
function = nil
|
36
|
+
options[:filter] = Filter.new(/^\.+$/) # remove . & .. dirs
|
37
|
+
options[:verbose] = false
|
38
|
+
insensitive = false
|
39
|
+
print_matches = false
|
40
|
+
quiet = false
|
41
|
+
silent = false
|
42
|
+
reverse = false
|
43
|
+
|
44
|
+
# more defaults... make configurable in the future
|
45
|
+
CommandLineInterface.confirm # confirm changes
|
46
|
+
options[:action] = :preview # dry-run mode
|
47
|
+
|
48
|
+
|
49
|
+
op.on_head('--noconfirm', 'Don\'t confirm.') {
|
50
|
+
CommandLineInterface.noconfirm
|
51
|
+
}
|
52
|
+
op.on_head('--confirm', 'Confirm before rename') {
|
53
|
+
CommandLineInterface.confirm
|
54
|
+
}
|
55
|
+
op.on_head('-t', '--test', 'Test run only, don\'t acually rename anything.') {
|
56
|
+
options[:action] = :preview
|
57
|
+
}
|
58
|
+
op.on_head('-c', '--commit', 'Commit changes and actually rename the files.') {
|
59
|
+
options[:action] = :commit
|
60
|
+
}
|
61
|
+
op.on_head('-l', '--list', 'List original file names in folders to operate on only.') {
|
62
|
+
function = :rename_replace
|
63
|
+
options[:action] = :list
|
64
|
+
@@results.list = true
|
65
|
+
}
|
66
|
+
|
67
|
+
op.on('-a', '--add NUMBER', Integer, 'Add to capture.') {|options[:add]|
|
68
|
+
function = :rename_add
|
69
|
+
}
|
70
|
+
op.on('-C', '--count', 'Replace capture with count.') {
|
71
|
+
function = :rename_count
|
72
|
+
}
|
73
|
+
op.on('--capture NUM', Integer, 'Replace the text in a specific capture.',
|
74
|
+
'Default: 1 (or whole match if there are no captures)') {|n|
|
75
|
+
options[:capture_num] = n
|
76
|
+
}
|
77
|
+
op.on('--file [FILE]', String,
|
78
|
+
'Use files.txt or FILE as source for replace strings.') {|file|
|
79
|
+
options[:source] = NameFileSource.new(file || 'files.txt')
|
80
|
+
function = :rename_name_source
|
81
|
+
options[:filter] = Filter.add(options[:filter], Filter.new(/^#{file || 'files.txt'}$/))
|
82
|
+
if file
|
83
|
+
options[:filter] = Filter.add(options[:filter], Filter.new(/^#{file}$/, nil, true))
|
84
|
+
end
|
85
|
+
}
|
86
|
+
op.on('-f', '--filter REGEXP', String,
|
87
|
+
'Remove matching files from the search.') {|f|
|
88
|
+
options[:filter] = Filter.add(options[:filter], Filter.new(PrepareRegexp.new(f)))
|
89
|
+
}
|
90
|
+
op.on('-F', '--keep REGEXP', String,
|
91
|
+
'Include only matching files in the search.') {|f|
|
92
|
+
options[:filter] = Filter.add(options[:filter], FilterNonMatches.new(PrepareRegexp.new(f)))
|
93
|
+
}
|
94
|
+
op.on('--force', 'Force rename even if a file will be replaced.') {
|
95
|
+
options[:force] = true
|
96
|
+
}
|
97
|
+
op.on('-i', '--fill REGEXP', String, 'Copy -s match from previous files and fill downwards, replacing the match for this pattern.') {|f|
|
98
|
+
options[:fill] = PrepareRegexp.new f
|
99
|
+
function = :rename_fill
|
100
|
+
}
|
101
|
+
op.on('-I', '--ignorecase', 'Make all REGEXP options case-insensitive.') {
|
102
|
+
insensitive = true
|
103
|
+
}
|
104
|
+
op.on('-n', '--roman', 'Toggle match to or from roman numerals.') {
|
105
|
+
function = :rename_roman
|
106
|
+
}
|
107
|
+
op.on('-m', '--mark [PATTERN]', 'Mark files if the captured pattern changes.',
|
108
|
+
'The capture in PATTERN will be replaced with --mark_text.',
|
109
|
+
'Default: /()$/') {|p|
|
110
|
+
function = :rename_mark_change
|
111
|
+
options[:replace_pattern] = PrepareRegexp.new(p || '()$')
|
112
|
+
options[:replace_text] ||= '--changed--'
|
113
|
+
}
|
114
|
+
op.on('--mark_text TEXT', 'Default: --changed--') {|t|
|
115
|
+
options[:replace_text] = t
|
116
|
+
}
|
117
|
+
op.on('-p', '--inpath REGEXP', String, 'Rename with match in full path.') {|p|
|
118
|
+
options[:pattern] = PrepareRegexp.new p
|
119
|
+
function = :rename_from_full_name
|
120
|
+
}
|
121
|
+
op.on('--prompt_name', 'Prompt for the new name of each file.') {
|
122
|
+
options[:source] = NamePromptSource.new
|
123
|
+
function = :rename_name_source
|
124
|
+
}
|
125
|
+
op.on('-r', '--replace [STRING]', String, 'Replace expression') {|r|
|
126
|
+
options[:replace] = r || ''
|
127
|
+
function = :rename_replace
|
128
|
+
}
|
129
|
+
op.on('-R', '--recursive', 'Operate on all files and folders recursively.') {
|
130
|
+
file_provider = Provider::File::Recursive
|
131
|
+
}
|
132
|
+
op.on('--reverse', 'Operate on files in reverse order.') {
|
133
|
+
reverse = true
|
134
|
+
}
|
135
|
+
op.on('--rm', 'Remove matching files.') {
|
136
|
+
function = :rename_remove
|
137
|
+
}
|
138
|
+
op.on('-s', '--search REGEXP', String, 'Search expression') {|s|
|
139
|
+
options[:search] = PrepareRegexp.new s
|
140
|
+
}
|
141
|
+
op.on('--sort', 'Sort output') { @@results.sorted = true }
|
142
|
+
op.on('--tape', 'Convert tape numbers ie. 1A, 1B, 2A, ... to regular numbers.') {
|
143
|
+
function = :rename_tape_numbers
|
144
|
+
}
|
145
|
+
op.on('-T', '--title', 'Convert capture to title case.') {
|
146
|
+
functon = :rename_capitalize
|
147
|
+
}
|
148
|
+
op.on('-u', '--up', 'Move files with match up to parent directory.') {
|
149
|
+
function = :rename_move_up
|
150
|
+
}
|
151
|
+
op.on('-q', '--quiet') { quiet = @@results.quiet = true }
|
152
|
+
op.on('-Q', '--silent') {
|
153
|
+
@@results.quiet = @@results.silent = silent = quiet = true;
|
154
|
+
options[:verbose] = print_matches = false }
|
155
|
+
op.on('-v', '--verbose', 'Vebose. Useful if you aren\'t getting the results you expect.') {
|
156
|
+
@@results.verbose = options[:verbose] = true
|
157
|
+
}
|
158
|
+
op.on('-V', '--more_verbose', 'Verbose + show breakdown of matchdata.') {
|
159
|
+
@@results.verbose = options[:verbose] = print_matches = true
|
160
|
+
}
|
161
|
+
op.on('-x', '--sideways', 'Display in rows instead of in columns.') {
|
162
|
+
@@results.sideways = true
|
163
|
+
}
|
164
|
+
op.on('-X', '--raw_output', 'Don\'t sort and keep everything on seperate lines.') {
|
165
|
+
@@results.lineways = true
|
166
|
+
}
|
167
|
+
|
168
|
+
paths = op.parse ARGV
|
169
|
+
|
170
|
+
if paths.empty?
|
171
|
+
paths = ['.']
|
172
|
+
end
|
173
|
+
|
174
|
+
if !options[:action]
|
175
|
+
puts 'An action must be specified: either -t, -c or -l' unless silent
|
176
|
+
exit
|
177
|
+
end
|
178
|
+
|
179
|
+
function = :rename_replace if !function
|
180
|
+
|
181
|
+
unless quiet
|
182
|
+
puts 'Rename File Set:'
|
183
|
+
puts "Using #{options[:action].to_s.upcase} mode."
|
184
|
+
if options[:confirm].is_a? Proc
|
185
|
+
puts 'CONFIRM changes.'
|
186
|
+
else
|
187
|
+
puts "DON'T confirm changes."
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
PrepareRegexp.each(options) do |k, v|
|
192
|
+
t = v.create(insensitive, print_matches, true) do |mode, output|
|
193
|
+
CommandLineInterface.output(mode, output)
|
194
|
+
end
|
195
|
+
t.k = k if print_matches
|
196
|
+
t
|
197
|
+
end
|
198
|
+
|
199
|
+
options[:file_provider] = file_provider.new(paths)
|
200
|
+
options[:file_provider].reverse if reverse
|
201
|
+
|
202
|
+
begin
|
203
|
+
renamer.run function, options do |mode, result, path, file|
|
204
|
+
CommandLineInterface.output(mode, result, path, file)
|
205
|
+
end
|
206
|
+
rescue RenamerError => e
|
207
|
+
CommandLineInterface.output(:error, "Error: #{e}")
|
208
|
+
ensure
|
209
|
+
@@results.display
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
CommandLineInterface.start
|
data/bin/rfsd.rb
ADDED
data/description.txt
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
This is a comprehensive utility for renaming sets of files. It makes full use of ruby's regular expressions to provide a number of operations including:
|
2
|
+
* add (capture a number and add +/-x to it)
|
3
|
+
* count (replace capture with a number)
|
4
|
+
* file source (specify a file which has a sequence of replacement strings, one per line)
|
5
|
+
* fill (capture text from one file name and use it on subsequent ones)
|
6
|
+
* roman (convert to and from roman numerals)
|
7
|
+
* mark changes (perform a replace only if a captured section of the file changes (uses 2 regexps) )
|
8
|
+
* in path (replace with text captured from the file's full path)
|
9
|
+
* prompt (prompt for a new name for each file)
|
10
|
+
* replace (regular search and replace)
|
11
|
+
* tape (replace 1A, 1B, 2A, 2B, ... with 1, 2, 3, 4, ...)
|
12
|
+
* title (Do Title Casing in the Proper English Way. It can Handle Punctuation too.)
|
13
|
+
* up (move files to parent directory)
|
14
|
+
|
15
|
+
It has a number of safety features:
|
16
|
+
* filters (exclusive or inclusive)
|
17
|
+
* won't overwrite existing files unless --force is specified
|
18
|
+
* yes/all/no/cancel confirmations on by default (currently command-line only)
|
19
|
+
* 3 modes: list, test, commit. Test is default
|
20
|
+
|
21
|
+
It includes a full-featured command-line interface and an almost-full-featured Fox 1.2 interface which works pretty well but needs a bit of attention.
|
22
|
+
|
23
|
+
I have also written a number of very cool/useful library classes or extensions which I will include, but which should eventually be in their own project(s).
|
24
|
+
|