mvmv 0.1.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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mvmv.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Junegunn Choi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # Mvmv
2
+
3
+ Simple batch renaming script.
4
+
5
+ ## Installation
6
+
7
+ $ gem install mvmv
8
+
9
+ ## Usage
10
+
11
+ ```
12
+ usage: mvmv [OPTIONS] <command> [<args>] <files>
13
+
14
+ commands:
15
+ mvmv prefix <prefix> <files>
16
+ mvmv suffix <suffix> <files>
17
+ mvmv name <name> <files>
18
+ mvmv name-suffix <suffix> <files>
19
+ mvmv ext <.extension> <files>
20
+ mvmv upper <files>
21
+ mvmv lower <files>
22
+
23
+ mvmv regexp <from> <to> <files>
24
+ mvmv regexpi <from> <to> <files>
25
+ mvmv name-regexp <from> <to> <files>
26
+ mvmv name-regexpi <from> <to> <files>
27
+
28
+ options:
29
+ -f, --force Force rename
30
+ --no-color Disable ANSI color codes
31
+ ```
32
+
33
+ ## Examples
34
+
35
+ ### Adding simple prefix and suffix to files
36
+
37
+ ```
38
+ mvmv prefix old_ *.txt
39
+ mvmv suffix .bak *.txt
40
+ ```
41
+
42
+ ### Numbering files
43
+
44
+ You can attach sequence numbers to files with a series of `#`s.
45
+ Depending on the number of `#`s, numbers will be padded with zeros.
46
+
47
+ ```
48
+ mvmv name Photo#### *.jpg *.gif *.png
49
+ mvmv name-suffix -## *.jpg
50
+ ```
51
+
52
+ ### Advanced renaming with regular expressions
53
+
54
+ `regexp` command performs regular expression substitutions. (`regexpi` is the case-insensitive version.)
55
+ `name-regexp` command performs regular expression subsitution only on the name parts of the given files.
56
+
57
+ ```
58
+ mvmv name-regexp '^(.*)_-_(.*)$' '\2 - \1' *.mp3
59
+ ```
60
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << 'lib' << 'test'
6
+ test.pattern = 'test/**/test_*.rb'
7
+ test.verbose = true
8
+ end
data/bin/mvmv ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'mvmv'
4
+
5
+ options = {}
6
+ usage = "
7
+ usage: mvmv [OPTIONS] <command> [<args>] <files>
8
+
9
+ commands:
10
+ mvmv prefix <prefix> <files>
11
+ mvmv suffix <suffix> <files>
12
+ mvmv name <name> <files>
13
+ mvmv name-suffix <suffix> <files>
14
+ mvmv ext <.extension> <files>
15
+ mvmv upper <files>
16
+ mvmv lower <files>
17
+
18
+ mvmv regexp <from> <to> <files>
19
+ mvmv regexpi <from> <to> <files>
20
+ mvmv name-regexp <from> <to> <files>
21
+ mvmv name-regexpi <from> <to> <files>
22
+
23
+ options:
24
+ -f, --force Force rename
25
+ --no-color Disable ANSI color codes
26
+ ".strip
27
+
28
+ options = {}
29
+ while ARGV.first =~ /^-/
30
+ case ARGV.shift
31
+ when '-f', '--force'
32
+ options[:force] = true
33
+ when '--no-color'
34
+ options[:color] = false
35
+ end
36
+ end
37
+
38
+ if ARGV.length < 2
39
+ puts usage
40
+ exit 1
41
+ end
42
+
43
+ command = ARGV[0].to_s.gsub('-', '_').to_sym
44
+ args = ARGV[1..-1]
45
+ mvmv = Mvmv.new options.fetch(:color, true)
46
+ begin
47
+ if options[:force]
48
+ mvmv.rename! command, *args
49
+ else
50
+ mvmv.rename command, *args
51
+ end
52
+ rescue ArgumentError => e
53
+ puts opts
54
+ exit 1
55
+ rescue Exception => e
56
+ exit 1
57
+ end
data/lib/mvmv.rb ADDED
@@ -0,0 +1,134 @@
1
+ require 'mvmv/version'
2
+ require 'mvmv/command'
3
+ require 'ansi'
4
+
5
+ class Mvmv
6
+ def initialize color = true, outstream = $stdout, instream = $stdin
7
+ @color = color
8
+ @outstream = outstream
9
+ @instream = instream
10
+ end
11
+
12
+ def convert_filenames symb, *args
13
+ unless Mvmv::Command.respond_to?(symb)
14
+ error "Invalid command: #{symb}"
15
+ end
16
+
17
+ arg_arity = Mvmv::Command.method(symb).arity - 1
18
+ if arg_arity >= args.length
19
+ error "Invalid number of parameters for #{symb}", ArgumentError
20
+ end
21
+
22
+ files = args[arg_arity..-1]
23
+ files.zip Mvmv::Command.send(symb, *(args[0, arg_arity] + [files]))
24
+ end
25
+
26
+ def rename symb, *args
27
+ rename_impl false, symb, *args
28
+ end
29
+
30
+ def rename! symb, *args
31
+ rename_impl true, symb, *args
32
+ end
33
+
34
+ private
35
+ def rename_impl force, symb, *args
36
+ pairs = convert_filenames symb, *args
37
+
38
+ flen = pairs.map(&:first).map(&:length).max
39
+ tlen = pairs.map(&:last).map(&:length).max
40
+
41
+ pairs.each do |pair|
42
+ from, to = pair
43
+ next if from == to || to.empty?
44
+ skip = false
45
+ while true
46
+ log [
47
+ ansi('[', :bold),
48
+ from.ljust(flen),
49
+ ansi('=>', :bold),
50
+ ansi(to.ljust(tlen), :blue, :bold),
51
+ ansi(']', :bold),
52
+ force ? nil : ansi('(', :yellow) +
53
+ ansi('y', :yellow, :bold) +
54
+ ansi('/', :yellow) +
55
+ 'n' +
56
+ ansi(')? ', :yellow)
57
+ ].compact.join(' ')
58
+
59
+ unless force
60
+ case @instream.gets
61
+ when nil
62
+ puts
63
+ next
64
+ when /^n/i
65
+ skip = true
66
+ break
67
+ when /^[^y\n]/i
68
+ next
69
+ end
70
+ end
71
+
72
+ unless File.exists?(from)
73
+ error " File not found: #{from}"
74
+ break
75
+ end
76
+
77
+ if !force && File.exists?(to)
78
+ skip = true
79
+ while true
80
+ log ansi(" #{to} already exists. Overwrite " +
81
+ ansi('(', :yellow) +
82
+ 'y' +
83
+ ansi('/', :yellow) +
84
+ ansi('n', :yellow, :bold) +
85
+ ansi(')? ', :yellow)
86
+ )
87
+
88
+ unless
89
+ case $stdin.gets
90
+ when nil
91
+ puts
92
+ next
93
+ when /^[n\n]/i
94
+ break
95
+ when /^y/i
96
+ skip = false
97
+ break
98
+ else
99
+ next
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ unless skip
106
+ begin
107
+ File.rename from, to
108
+ logln " Renamed", :green
109
+ rescue Exception => e
110
+ error " Failed to rename #{from}"
111
+ end
112
+ end
113
+ break
114
+ end
115
+ end
116
+ end
117
+
118
+ def ansi msg, *colors
119
+ (@color && !colors.empty?) ? ANSI::Code.ansi(*colors) { msg } : msg
120
+ end
121
+
122
+ def log msg, *colors
123
+ @outstream.print ansi(msg, *colors)
124
+ end
125
+
126
+ def logln msg, *colors
127
+ @outstream.puts ansi(msg, *colors)
128
+ end
129
+
130
+ def error message, x = Exception
131
+ logln message, :red, :bold
132
+ raise x.new(message)
133
+ end
134
+ end
@@ -0,0 +1,83 @@
1
+ class Mvmv
2
+ module Command
3
+ class Sequencer
4
+ def initialize n = 1
5
+ @n = n - 1
6
+ end
7
+
8
+ def convert str
9
+ @n += 1
10
+ str.gsub(/#+/) { |x| @n.to_s.rjust(x.length, '0') }
11
+ end
12
+ end
13
+
14
+ class << self
15
+ def name n, files
16
+ seq = Sequencer.new
17
+ files.map { |file|
18
+ seq.convert(n) + File.extname(file)
19
+ }
20
+ end
21
+
22
+ def prefix p, files
23
+ seq = Sequencer.new
24
+ files.map { |file| seq.convert(p) + file }
25
+ end
26
+
27
+ def suffix s, files
28
+ seq = Sequencer.new
29
+ files.map { |file| file + seq.convert(s) }
30
+ end
31
+
32
+ def name_suffix s, files
33
+ seq = Sequencer.new
34
+ files.map { |file|
35
+ ext = File.extname(file)
36
+ file.chomp(ext) + seq.convert(s) + ext
37
+ }
38
+ end
39
+
40
+ def ext x, files
41
+ files.map { |file|
42
+ ext = File.extname(file)
43
+ file.chomp(ext) + x
44
+ }
45
+ end
46
+
47
+ def upper files
48
+ files.map(&:upcase)
49
+ end
50
+
51
+ def lower files
52
+ files.map(&:downcase)
53
+ end
54
+
55
+ def regexpi f, t, files
56
+ seq = Sequencer.new
57
+ files.map { |file|
58
+ seq.convert file.gsub(Regexp.compile(f, Regexp::IGNORECASE), t)
59
+ }
60
+ end
61
+
62
+ def regexp f, t, files
63
+ seq = Sequencer.new
64
+ files.map { |file|
65
+ seq.convert file.gsub(Regexp.compile(f), t)
66
+ }
67
+ end
68
+
69
+ def name_regexpi f, t, files
70
+ regexpi(f, t, files.map { |file|
71
+ file.chomp(File.extname file)
72
+ }).zip(files.map { |file| File.extname file }).map(&:join)
73
+ end
74
+
75
+ def name_regexp f, t, files
76
+ regexp(f, t, files.map { |file|
77
+ file.chomp(File.extname file)
78
+ }).zip(files.map { |file| File.extname file }).map(&:join)
79
+ end
80
+ end
81
+ end#Command
82
+ end
83
+
@@ -0,0 +1,3 @@
1
+ class Mvmv
2
+ VERSION = "0.1.0"
3
+ end
data/mvmv.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/mvmv/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Junegunn Choi"]
6
+ gem.email = ["junegunn.c@gmail.com"]
7
+ gem.description = %q{Simple batch renaming}
8
+ gem.summary = %q{Simple batch renaming}
9
+ gem.homepage = "https://github.com/junegunn/mvmv"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "mvmv"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Mvmv::VERSION
17
+ gem.add_runtime_dependency 'ansi', '~> 1.4.2'
18
+ gem.add_development_dependency 'test-unit'
19
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ # DISCLAIMER:
5
+ # Not a real test!
6
+ # Just a helper script for running scripts with local source
7
+
8
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../lib')
9
+ load File.join(File.dirname(__FILE__), '../bin/', File.basename(ARGV.shift))
data/test/test_mvmv.rb ADDED
@@ -0,0 +1,85 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ require 'mvmv'
5
+
6
+ class TestMvmv < Test::Unit::TestCase
7
+ def test_name_conversion
8
+ m = Mvmv.new
9
+ input = %w[aaa.jpg bbb.GIF ccc.jpg.png]
10
+ assert_equal input.zip(%w[photo001.jpg photo002.GIF photo003.png]), m.convert_filenames(:name, 'photo###', *input)
11
+ assert_equal input.zip(%w[old_aaa.jpg old_bbb.GIF old_ccc.jpg.png]), m.convert_filenames(:prefix, 'old_', *input)
12
+ assert_equal input.zip(%w[001-aaa.jpg 002-bbb.GIF 003-ccc.jpg.png]), m.convert_filenames(:prefix, '###-', *input)
13
+ assert_equal input.zip(%w[aaa.jpg.0001 bbb.GIF.0002 ccc.jpg.png.0003]), m.convert_filenames(:suffix, '.####', *input)
14
+ assert_equal input.zip(%w[aaa-0001.jpg bbb-0002.GIF ccc.jpg-0003.png]), m.convert_filenames(:name_suffix, '-####', *input)
15
+ assert_equal input.zip(%w[aaa.jpeg bbb.jpeg ccc.jpg.jpeg]), m.convert_filenames(:ext, '.jpeg', *input)
16
+ assert_equal input.zip(%w[AAA.JPG BBB.GIF CCC.JPG.PNG]), m.convert_filenames(:upper, *input)
17
+ assert_equal input.zip(%w[aaa.jpg bbb.gif ccc.jpg.png]), m.convert_filenames(:lower, *input)
18
+
19
+ input = %w[abc.jpg xyz.GIF ijk.jpg.png]
20
+ assert_equal input.zip(%w[cba01.jpg zyx02.GIF kji03.jpg.png]), m.convert_filenames(:regexp, '^([a-z])([a-z])([a-z])', '\3\2\1##', *input)
21
+ assert_equal input.zip(input), m.convert_filenames(:regexp, '^([A-Z])([A-Z])([A-Z])', '\3\2\1##', *input)
22
+ assert_equal input.zip(%w[cba01.jpg zyx02.GIF kji03.jpg.png]), m.convert_filenames(:regexpi, '^([A-Z])([a-z])([A-Z])', '\3\2\1##', *input)
23
+
24
+ assert_equal input.zip(%w[cba01.gpj01 zyx02.GIF kji03.gpj03.gnp03]), m.convert_filenames(:regexp, '([a-z])([a-z])([a-z])', '\3\2\1##', *input)
25
+
26
+ input = %w[Abc.jpg xyz.GIF ijk.jpg.png]
27
+ assert_equal input.zip(%w[Abc.jpg zyx02.GIF kji03.gpj03.png]), m.convert_filenames(:name_regexp, '([a-z])([a-z])([a-z])', '\3\2\1##', *input)
28
+ assert_equal input.zip(%w[cbA01.jpg zyx02.GIF kji03.gpj03.png]), m.convert_filenames(:name_regexpi, '([a-z])([a-z])([a-z])', '\3\2\1##', *input)
29
+ end
30
+
31
+ def test_rename!
32
+ m = Mvmv.new
33
+
34
+ input = %w[aaa.jpg bbb.gif ccc.jpg.png]
35
+ pairs = m.convert_filenames :ext, '.jpeg', *input
36
+
37
+ pairs.each do |pair|
38
+ system "rm -v #{pair.join ' '}"
39
+ end
40
+
41
+ input.each do |file|
42
+ system "touch #{file}"
43
+ end
44
+ system "touch #{pairs.last.last}"
45
+
46
+ pairs.each do |pair|
47
+ assert File.exist?(pair.first), 'File should exist'
48
+ assert !File.exist?(pair.last), 'File should not exist' unless pair.last == pairs.last.last
49
+ end
50
+
51
+ m.rename! :ext, '.jpeg', *input
52
+
53
+ pairs.each do |pair|
54
+ assert !File.exist?(pair.first), 'File should not exist'
55
+ assert File.exist?(pair.last), 'File should exist'
56
+ end
57
+
58
+ pairs.each do |pair|
59
+ system "rm -v #{pair.join ' '}"
60
+ end
61
+ end
62
+
63
+ def test_rename_dir
64
+ m = Mvmv.new
65
+
66
+ input = %w[aaa bbb ccc]
67
+ pairs = m.convert_filenames :name, '##', *input
68
+ pairs.each do |pair|
69
+ system "rm -rfv #{pair.join ' '}"
70
+ system "mkdir -pv #{pair.first}"
71
+ end
72
+
73
+ m.rename! :name, '##', *input
74
+
75
+ pairs.each do |pair|
76
+ assert !File.exist?(pair.first), 'Directory should not exist'
77
+ assert File.exist?(pair.last), 'Directory should exist'
78
+ assert File.directory?(pair.last), 'Should be a directory'
79
+ end
80
+
81
+ pairs.each do |pair|
82
+ system "rm -rfv #{pair.join ' '}"
83
+ end
84
+ end
85
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mvmv
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Junegunn Choi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ansi
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.4.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.4.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: test-unit
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Simple batch renaming
47
+ email:
48
+ - junegunn.c@gmail.com
49
+ executables:
50
+ - mvmv
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - LICENSE
57
+ - README.md
58
+ - Rakefile
59
+ - bin/mvmv
60
+ - lib/mvmv.rb
61
+ - lib/mvmv/command.rb
62
+ - lib/mvmv/version.rb
63
+ - mvmv.gemspec
64
+ - test/bin_helper.rb
65
+ - test/test_mvmv.rb
66
+ homepage: https://github.com/junegunn/mvmv
67
+ licenses: []
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 1.8.24
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Simple batch renaming
90
+ test_files:
91
+ - test/bin_helper.rb
92
+ - test/test_mvmv.rb