mass_renamer 0.9.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/bin/mass_renamer +3 -0
- data/bin/renamer +12 -0
- data/lib/renamer/command_line.rb +68 -0
- data/lib/renamer/driver.rb +136 -0
- data/lib/renamer/free.rb +75 -0
- data/lib/renamer/version.rb +3 -0
- data/lib/renamer.rb +4 -0
- metadata +55 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8cb99e36d38c302b2c0c096f491376f389478fdf
|
4
|
+
data.tar.gz: 7eb9b871ed283a1452f2b7d1448ef8dd0216139c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d8c9a507a59b948f00924bdeec27c1223952494df820b971bde0cb887d5a077cb62cc54d7f27f4e9138a4f6e3d482c27ae3bdace67b9f3cda5a4f25497b0f99d
|
7
|
+
data.tar.gz: 341df60426ae34871af5780d633535c87ea230ebed06af7ccd1578a08fbf2ae31c3208a6e600e1abdf2bcc2b10feee96920d54337350c4d8b461618f8de3f477
|
data/bin/mass_renamer
ADDED
data/bin/renamer
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Renamer
|
4
|
+
|
5
|
+
class Command_Line
|
6
|
+
def initialize argv = ARGV
|
7
|
+
opts = parse argv
|
8
|
+
@driver = Driver.new opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def rename!
|
12
|
+
@driver.rename!
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse argv
|
16
|
+
opts = {}
|
17
|
+
OptionParser.new do |opt|
|
18
|
+
opt.banner = 'Usage: renamer [DIRECTORY] [OPTIONS]'
|
19
|
+
opt.separator ''
|
20
|
+
opt.separator 'DIRECTORY in which you want to rename. If not'
|
21
|
+
opt.separator 'provided, `pwd` is used.'
|
22
|
+
opt.separator ''
|
23
|
+
opt.separator 'Editor to use is determined by this priority:'
|
24
|
+
opt.separator ' --editor'
|
25
|
+
opt.separator ' $EDITOR'
|
26
|
+
opt.separator ' vim'
|
27
|
+
opt.separator ''
|
28
|
+
opt.separator 'Options:'
|
29
|
+
|
30
|
+
opt.on('-h', '--help', 'Print usage') do
|
31
|
+
puts opt
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
opt.on('-d', '--dry', 'Dry run') do
|
35
|
+
opts[:dry] = true
|
36
|
+
end
|
37
|
+
opt.on('-r', '--recursive', 'Recurse into subdirectories') do
|
38
|
+
opts[:recursive] = true
|
39
|
+
end
|
40
|
+
opt.on('-D', '--no-delete', 'Complete disables delete function') do
|
41
|
+
opts[:no_delete] = true
|
42
|
+
end
|
43
|
+
opt.on('-v', '--verify', 'Ask for consent before doing each action') do
|
44
|
+
opts[:verify] = true
|
45
|
+
end
|
46
|
+
opt.on('-k', '--keep-going', 'Keep going after failure') do
|
47
|
+
opts[:keep_going] = true
|
48
|
+
end
|
49
|
+
opt.on('-V', '--verbose', 'Be verbose') do
|
50
|
+
opts[:verbose] = true
|
51
|
+
end
|
52
|
+
opt.on('--version', 'Print version') do
|
53
|
+
opts[:version] = true
|
54
|
+
end
|
55
|
+
opt.on('-e', '--editor EDITOR', 'Editor to use') do |editor|
|
56
|
+
opts[:editor] = editor
|
57
|
+
end
|
58
|
+
opt.on('-f', '--filter REGEX', Regexp, 'Regex used to filter files') do |filter|
|
59
|
+
opts[:filter] = filter
|
60
|
+
end
|
61
|
+
end.parse!(argv)
|
62
|
+
opts[:dir] = argv[0] || Dir::pwd
|
63
|
+
opts[:editor] ||= ENV['EDITOR'] || 'vim'
|
64
|
+
opts
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Renamer
|
5
|
+
|
6
|
+
class Filesystem_Driver
|
7
|
+
|
8
|
+
def initialize ask: , dry:, verbose:, no_delete:
|
9
|
+
@ask = ask
|
10
|
+
@dry = dry
|
11
|
+
@verbose = verbose
|
12
|
+
@no_delete = no_delete
|
13
|
+
end
|
14
|
+
|
15
|
+
def ask msg, from, to = nil
|
16
|
+
print "#{msg} '#{from}'#{to ? " -> '#{to}'" : '' }? [YN]: "
|
17
|
+
gets.chomp.downcase == ?y
|
18
|
+
end
|
19
|
+
|
20
|
+
def remove! from
|
21
|
+
raise "Deletes were disables." if @no_delete
|
22
|
+
begin
|
23
|
+
puts "rm -r '#{from}'" if @dry or @verbose
|
24
|
+
if @ask
|
25
|
+
return unless ask("Remove file", from)
|
26
|
+
end
|
27
|
+
return if @dry
|
28
|
+
FileUtils.remove_entry from
|
29
|
+
rescue StandardError => e
|
30
|
+
STDERR.puts "remove of '#{from}' failed: #{e.message}"
|
31
|
+
raise
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def copy! from, to
|
36
|
+
begin
|
37
|
+
puts "cp -r '#{from}' '#{to}'" if @dry or @verbose
|
38
|
+
if @ask
|
39
|
+
return unless ask("Copy", from, to)
|
40
|
+
end
|
41
|
+
return if @dry
|
42
|
+
FileUtils.mkdir_p File.dirname(to)
|
43
|
+
FileUtils.copy_entry from, to, preserve: true, remove_destination: true
|
44
|
+
rescue StandardError => e
|
45
|
+
STDERR.puts "copy '#{from}' -> '#{to}' failed: #{e.message}"
|
46
|
+
raise
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def move! from, to
|
51
|
+
begin
|
52
|
+
puts "mv '#{from}' '#{to}'" if @dry or @verbose
|
53
|
+
if @ask
|
54
|
+
return unless ask("Move", from, to)
|
55
|
+
end
|
56
|
+
return if @dry
|
57
|
+
FileUtils.mkdir_p File.dirname(to)
|
58
|
+
File.rename from, to
|
59
|
+
rescue StandardError => e
|
60
|
+
STDERR.puts "move '#{from}' -> '#{to}' failed: #{e.message}"
|
61
|
+
raise
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
class Driver
|
68
|
+
include Free
|
69
|
+
|
70
|
+
def initialize opts
|
71
|
+
@opts = opts
|
72
|
+
validate_environment!
|
73
|
+
end
|
74
|
+
|
75
|
+
def rename!
|
76
|
+
files = gather_files(
|
77
|
+
@opts[:dir],
|
78
|
+
recursive: @opts[:recursive],
|
79
|
+
filter: @opts[:filter]
|
80
|
+
)
|
81
|
+
renames = invoke_editor files
|
82
|
+
do_renames! renames
|
83
|
+
end
|
84
|
+
|
85
|
+
def do_renames! renames
|
86
|
+
fd = Filesystem_Driver.new(
|
87
|
+
ask: @opts[:ask],
|
88
|
+
dry: @opts[:dry],
|
89
|
+
verbose: @opts[:verbose],
|
90
|
+
no_delete: @opts[:no_delete]
|
91
|
+
)
|
92
|
+
|
93
|
+
renames.each do |from, to|
|
94
|
+
from = File.expand_path from
|
95
|
+
to.map!(&File.method(:expand_path))
|
96
|
+
|
97
|
+
begin
|
98
|
+
case to.length
|
99
|
+
when 0
|
100
|
+
fd.remove! from
|
101
|
+
when 1
|
102
|
+
to = to.first
|
103
|
+
next if from == to
|
104
|
+
fd.move! from, to
|
105
|
+
else
|
106
|
+
to.each { |to| fd.copy! from, to }
|
107
|
+
fd.remove! from
|
108
|
+
end
|
109
|
+
rescue
|
110
|
+
next if @opts[:keep_going]
|
111
|
+
STDERR.puts "Something failed, stopping."
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def invoke_editor files
|
118
|
+
tmpfile = Tempfile.new
|
119
|
+
begin
|
120
|
+
tmpfile.write generate_file_to_edit(files)
|
121
|
+
tmpfile.flush
|
122
|
+
system(@opts[:editor], tmpfile.path)
|
123
|
+
tmpfile.rewind
|
124
|
+
parse_renames(tmpfile.read)
|
125
|
+
ensure
|
126
|
+
tmpfile.close
|
127
|
+
tmpfile.unlink
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def validate_environment!
|
132
|
+
raise IOError, "Directory does not exist." unless File.exist? @opts[:dir]
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
data/lib/renamer/free.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Renamer
|
5
|
+
module Free
|
6
|
+
|
7
|
+
def gather_files_impl dir, recursive
|
8
|
+
children = dir.children false
|
9
|
+
sort_files! children
|
10
|
+
if recursive
|
11
|
+
children.collect! do |c|
|
12
|
+
filepath = dir + c
|
13
|
+
if filepath.directory?
|
14
|
+
[filepath, gather_files_impl(filepath, recursive)]
|
15
|
+
else
|
16
|
+
filepath
|
17
|
+
end
|
18
|
+
end.flatten!
|
19
|
+
end
|
20
|
+
children
|
21
|
+
end
|
22
|
+
|
23
|
+
def gather_files(dir, recursive: false, filter: nil)
|
24
|
+
files = gather_files_impl Pathname.new(dir), recursive
|
25
|
+
filter_files! files, filter if filter
|
26
|
+
exclude_weird_filenames! files
|
27
|
+
files
|
28
|
+
end
|
29
|
+
|
30
|
+
def filter_files! files, filter
|
31
|
+
files.select! { |i| i.to_s[filter] } if filter
|
32
|
+
end
|
33
|
+
|
34
|
+
def exclude_weird_filenames! files
|
35
|
+
files.reject! { |f| f = f.to_s; f.include?("\n") or f.start_with?(" ") }
|
36
|
+
end
|
37
|
+
|
38
|
+
def sort_files! files
|
39
|
+
files.sort! do |a,b|
|
40
|
+
if a.directory? and b.directory?
|
41
|
+
a <=> b
|
42
|
+
elsif a.directory?
|
43
|
+
-1
|
44
|
+
elsif b.directory?
|
45
|
+
1
|
46
|
+
else
|
47
|
+
a <=> b
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def generate_file_to_edit files
|
53
|
+
res = ""
|
54
|
+
files.each do |f|
|
55
|
+
res << f.to_s << "\n\t" << f.to_s << "\n"
|
56
|
+
end
|
57
|
+
res
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_renames str
|
61
|
+
lines = str.lines.map(&:chomp)
|
62
|
+
renames = []
|
63
|
+
until lines.empty?
|
64
|
+
filename = lines.shift
|
65
|
+
targets = []
|
66
|
+
while lines[0] and lines[0] =~ /^\s/
|
67
|
+
targets << lines.shift.strip
|
68
|
+
end
|
69
|
+
renames << [filename, targets]
|
70
|
+
end
|
71
|
+
renames
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
data/lib/renamer.rb
ADDED
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mass_renamer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gray Wolf
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-06-24 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |
|
14
|
+
Tool for renaming multiple files at once with easy. By
|
15
|
+
employing external editor of your choice, you can use
|
16
|
+
all the power you editor offers.
|
17
|
+
email: wolf@wolfsden.cz
|
18
|
+
executables:
|
19
|
+
- renamer
|
20
|
+
- mass_renamer
|
21
|
+
extensions: []
|
22
|
+
extra_rdoc_files: []
|
23
|
+
files:
|
24
|
+
- bin/mass_renamer
|
25
|
+
- bin/renamer
|
26
|
+
- lib/renamer.rb
|
27
|
+
- lib/renamer/command_line.rb
|
28
|
+
- lib/renamer/driver.rb
|
29
|
+
- lib/renamer/free.rb
|
30
|
+
- lib/renamer/version.rb
|
31
|
+
homepage: https://github.com/graywolf/renamer
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
metadata: {}
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 2.6.11
|
52
|
+
signing_key:
|
53
|
+
specification_version: 4
|
54
|
+
summary: Rename multiple files with ease!
|
55
|
+
test_files: []
|