nrename 0.0.1

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/bin/nrename ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path '../../lib/nrename', __FILE__
4
+
5
+ Nrename.run ARGV.dup
@@ -0,0 +1,35 @@
1
+ Feature: Options processing
2
+ In order to use the program conveniently
3
+ As a user
4
+ I want options to be parsed correctly
5
+
6
+ Scenario: Displaying help when run with "-h"
7
+ When I run `nrename -h`
8
+ Then the exit status should be 0
9
+ And the stdout should contain "Usage: nrename "
10
+
11
+ Scenario: Displaying help when run without any options
12
+ When I run `nrename`
13
+ Then the exit status should be 0
14
+ And the stdout should contain "Usage: nrename "
15
+
16
+ Scenario: Displaying version
17
+ When I run `nrename --version`
18
+ Then the exit status should be 0
19
+ And the stdout should match /^(\d+)\.\g'1'\.\g'1'$/
20
+
21
+ Scenario: Passing valid directory name
22
+ Given a directory named "foo_bar"
23
+ When I run `nrename foo_bar`
24
+ Then the exit status should be 0
25
+
26
+ Scenario: Passing invalid directory name
27
+ When I run `nrename no_dir`
28
+ Then the exit status should be 1
29
+ And the stderr should contain "no_dir is not a valid directory."
30
+
31
+ Scenario: Passing file instead of directory
32
+ Given an empty file named "foo"
33
+ When I run `nrename foo`
34
+ Then the exit status should be 1
35
+ And the stderr should contain "foo is not a valid directory."
@@ -0,0 +1,86 @@
1
+ Feature: Renaming files
2
+ In order to get my files nicely sortable
3
+ As a user
4
+ I want program to rename files correctly
5
+
6
+ Scenario: Renaming files in specified directory
7
+ Given a directory named "dir"
8
+ And the following empty files inside directory "dir":
9
+ | 1.txt |
10
+ | 10.txt |
11
+ | 0023.txt |
12
+ | 101.txt |
13
+ | 200.txt |
14
+ When I run `nrename -X dir`
15
+ Then the exit status should be 0
16
+ And the following files should exist inside directory "dir":
17
+ | 001.txt |
18
+ | 010.txt |
19
+ | 023.txt |
20
+ | 101.txt |
21
+ | 200.txt |
22
+
23
+ Scenario: Renaming files in current directory
24
+ Given a directory named "dir"
25
+ And the following empty files inside directory "dir":
26
+ | 1.txt |
27
+ | 10.txt |
28
+ When I cd to "dir"
29
+ And I run `nrename -X`
30
+ Then the exit status should be 0
31
+ And the following files should exist:
32
+ | 01.txt |
33
+ | 10.txt |
34
+
35
+ Scenario: Dry-run
36
+ Given a directory named "dir"
37
+ And the following empty files inside directory "dir":
38
+ | 1.txt |
39
+ | 10.txt |
40
+ | 0023.txt |
41
+ When I cd to "dir"
42
+ When I run `nrename`
43
+ Then the exit status should be 0
44
+ And the following files should exist:
45
+ | 1.txt |
46
+ | 10.txt |
47
+ | 0023.txt |
48
+ And the following files should not exist:
49
+ | 01.txt |
50
+ | 23.txt |
51
+
52
+ Scenario: Renaming files in multiple directories
53
+ Given a directory named "foo"
54
+ And a directory named "bar"
55
+ And the following empty files inside directory "foo":
56
+ | 1.txt |
57
+ | 010.txt |
58
+ And the following empty files inside directory "bar":
59
+ | 33.txt |
60
+ | 01234.txt |
61
+ And I run `nrename -X foo bar`
62
+ Then the exit status should be 0
63
+ And the following files should exist inside directory "foo":
64
+ | 01.txt |
65
+ | 10.txt |
66
+ And the following files should exist inside directory "bar":
67
+ | 0033.txt |
68
+ | 1234.txt |
69
+
70
+ Scenario: Renaming files recursively
71
+ Given a directory named "foo"
72
+ And a directory named "bar"
73
+ And the following empty files inside directory "foo":
74
+ | 1.txt |
75
+ | 010.txt |
76
+ And the following empty files inside directory "bar":
77
+ | 33.txt |
78
+ | 01234.txt |
79
+ And I run `nrename -XR`
80
+ Then the exit status should be 0
81
+ And the following files should exist inside directory "foo":
82
+ | 01.txt |
83
+ | 10.txt |
84
+ And the following files should exist inside directory "bar":
85
+ | 0033.txt |
86
+ | 1234.txt |
@@ -0,0 +1,19 @@
1
+ require 'aruba/cucumber'
2
+
3
+ ENV['PATH'] = "#{File.expand_path __FILE__, '../../../bin'}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
4
+
5
+ Given(/^the following empty files inside directory "([^"]*)":$/) do |directory, files|
6
+ files.raw.each do |file_row|
7
+ write_file "#{directory}/#{file_row[0]}", ''
8
+ end
9
+ end
10
+
11
+ Then(/^the stdout should match \/([^\/]*)\/$/) do |expected|
12
+ assert_matching_output expected, all_stdout
13
+ end
14
+
15
+ Then(/^the following files should exist inside directory "([^"]*)":$/) do |directory, files|
16
+ files.raw.each do |file_row|
17
+ check_file_presence ["#{directory}/#{file_row[0]}"], true
18
+ end
19
+ end
@@ -0,0 +1,60 @@
1
+ require 'pathname'
2
+ require 'fileutils'
3
+
4
+ module Nrename
5
+ class Directory
6
+ def initialize(dir)
7
+ @dir = Pathname.new dir
8
+
9
+ unless @dir.absolute?
10
+ fail ArgumentError, 'directory path should be absolute.'
11
+ end
12
+
13
+ opts = Nrename.options
14
+
15
+ @verbose = opts.verbose
16
+ @execute = opts.execute
17
+ @pattern = opts.pattern
18
+ end
19
+
20
+ def numbered_files
21
+ @numbered_files ||= @dir.children
22
+ .reject(&:directory?)
23
+ .select { |file| file.basename.to_s =~ @pattern }
24
+ end
25
+
26
+ def num_field_length
27
+ @num_field_length ||= max_number.to_s.size
28
+ end
29
+
30
+ def max_number
31
+ numbered_files.map(&method(:number_for)).max
32
+ end
33
+
34
+ def normalize
35
+ numbered_files.each do |old|
36
+ new = normalized_name_for(old)
37
+ next if old == new
38
+ FileUtils.mv old, new, {
39
+ :noop => !@execute,
40
+ :verbose => @verbose
41
+ }
42
+ end
43
+ end
44
+
45
+ def normalized_name_for(path)
46
+ dirname, filename = path.split
47
+ new_filename = filename.to_s
48
+ new_filename[@pattern, 1] = adjusted_number_string_for(path)
49
+ dirname + new_filename
50
+ end
51
+
52
+ def number_for(path)
53
+ path.basename.to_s[@pattern, 1].to_i
54
+ end
55
+
56
+ def adjusted_number_string_for(path)
57
+ number_for(path).to_s.rjust num_field_length, '0'
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,82 @@
1
+ require 'optparse'
2
+ require 'ostruct'
3
+
4
+ module Nrename
5
+ module Options
6
+ def self.parse(args)
7
+ default_options = {
8
+ :dirs => [],
9
+ :execute => false,
10
+ :pattern => /(\d+)/,
11
+ :recursive => false,
12
+ :verbose => true
13
+ }
14
+
15
+ options = OpenStruct.new default_options
16
+
17
+ executable_name = File.basename $PROGRAM_NAME
18
+
19
+ # display help if called through 'nrename' executable
20
+ # and without arguments
21
+ if args.empty? && executable_name == 'nrename'
22
+ args << '--help'
23
+ end
24
+
25
+ OptionParser.new do |opts|
26
+ opts.banner = "Usage: #{executable_name} [OPTINS] [DIR]..."
27
+
28
+ opts.separator ''
29
+ opts.separator 'Options:'
30
+
31
+ opts.on '-X', '--execute', "Do actual work" do |x|
32
+ options.execute = x
33
+ end
34
+
35
+ opts.on '-R', '--recursive',
36
+ 'Process given directories recursively' do |rec|
37
+ options.recursive = rec
38
+ end
39
+
40
+ opts.on '-v', '--[no-]verbose', 'Run verbosely' do |v|
41
+ options.verbose = v
42
+ end
43
+
44
+ opts.on '-h', '--help', 'Display this message' do
45
+ puts opts
46
+ exit
47
+ end
48
+
49
+ opts.on '--version', 'Display version' do
50
+ puts VERSION
51
+ exit
52
+ end
53
+ end.parse!(args)
54
+
55
+ args.each do |arg|
56
+ dir = File.expand_path arg
57
+ if File.directory? dir
58
+ options.dirs << dir
59
+ else
60
+ warn "#{dir} is not a valid directory."
61
+ exit 1
62
+ end
63
+ end
64
+
65
+ if options.dirs.empty?
66
+ options.dirs << File.expand_path('.')
67
+ end
68
+
69
+ if options.recursive
70
+ options.dirs.dup.each do |dir|
71
+ Dir.glob "#{dir}/**/" do |subdir|
72
+ options.dirs << subdir.chomp('/')
73
+ end
74
+ end
75
+ end
76
+
77
+ options.dirs.uniq!
78
+
79
+ options
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,3 @@
1
+ module Nrename
2
+ VERSION = "0.0.1"
3
+ end
data/lib/nrename.rb ADDED
@@ -0,0 +1,20 @@
1
+ $:.push File.expand_path(File.dirname __FILE__)
2
+
3
+ require 'nrename/version'
4
+ require 'nrename/directory'
5
+ require 'nrename/options'
6
+
7
+ module Nrename
8
+ def self.options
9
+ # return default options if not alredy set by .run():
10
+ @options ||= Options.parse []
11
+ end
12
+
13
+ def self.run(args=[])
14
+ @options = Options.parse args
15
+
16
+ options.dirs
17
+ .map { |dir| Directory.new dir }
18
+ .each &:normalize
19
+ end
20
+ end
@@ -0,0 +1,142 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nrename::Directory do
4
+ let(:test_dir) { '/tmp/test_dir' }
5
+
6
+ after :each do
7
+ rm_rf test_dir
8
+ end
9
+
10
+ describe '#numbered_files' do
11
+ it 'correctly determines number of numbered files' do
12
+ inside test_dir do
13
+ touch %w[1.rb 2.rb 3.rb]
14
+ end
15
+
16
+ dir = Nrename::Directory.new test_dir
17
+ dir.should have(3).numbered_files
18
+ end
19
+
20
+ it 'returns empty array when there is no num. files in dir' do
21
+ mkdir test_dir
22
+ dir = Nrename::Directory.new test_dir
23
+ dir.should have(:no).numbered_files
24
+ end
25
+
26
+ it 'does not care about non-numbered files' do
27
+ inside test_dir do
28
+ touch %w[1.rb 2.rb 3.rb foo.rb bar baz.java]
29
+ end
30
+
31
+ dir = Nrename::Directory.new test_dir
32
+ dir.should have(3).numbered_files
33
+ end
34
+
35
+ it 'does not care about directories' do
36
+ inside test_dir do
37
+ touch %w[1.rb 2.rb 3.rb]
38
+ mkdir %w[1 2 03 40 55]
39
+ end
40
+
41
+ dir = Nrename::Directory.new test_dir
42
+ dir.should have(3).numbered_files
43
+ end
44
+ end
45
+
46
+ describe '#field_length' do
47
+ it 'returns minimal number of digits to fit num of any file' do
48
+ inside test_dir do
49
+ touch %w[1 2 3 444 3234 5 6 7]
50
+ end
51
+
52
+ dir = Nrename::Directory.new test_dir
53
+ dir.num_field_length.should be == 4
54
+ end
55
+
56
+ it 'ignores starting zeros in number' do
57
+ inside test_dir do
58
+ touch %w[001 002 004 035]
59
+ end
60
+
61
+ dir = Nrename::Directory.new test_dir
62
+ dir.num_field_length.should be == 2
63
+ end
64
+ end
65
+
66
+ describe '#max_number' do
67
+ it 'returns maximum number for all file names' do
68
+ inside test_dir do
69
+ touch %w[1 2 3]
70
+ end
71
+
72
+ dir = Nrename::Directory.new test_dir
73
+ dir.max_number.should be == 3
74
+ end
75
+
76
+ it 'is not fooled by fancy file names' do
77
+ inside test_dir do
78
+ touch %w[001 foo003bar.java o98.c 30_999.rb]
79
+ end
80
+
81
+ dir = Nrename::Directory.new test_dir
82
+ dir.max_number.should be == 98
83
+ end
84
+ end
85
+
86
+ describe '#normalize' do
87
+ before do
88
+ Nrename.options.stub execute: true
89
+ end
90
+
91
+ it 'renames files so than they can be sorted properly' do
92
+ inside test_dir do
93
+ touch %w[1 2 3 10 11 004 005 006]
94
+ end
95
+
96
+ # turn off verbose output:
97
+ Nrename.options.stub verbose: false
98
+
99
+ dir = Nrename::Directory.new test_dir
100
+ dir.normalize
101
+
102
+ expected = %w[01 02 03 04 05 06 10 11]
103
+ renamed_files = Dir.entries(test_dir)
104
+ expected.each { |file| renamed_files.should include file }
105
+ end
106
+ end
107
+
108
+ describe '#normalized_name_for' do
109
+ it 'returns normalized name for file' do
110
+ dir = Nrename::Directory.new test_dir
111
+ file = Pathname.new(test_dir) + '1.txt'
112
+ dir.stub num_field_length: 4
113
+ new_name = dir.normalized_name_for(file).basename.to_s
114
+ new_name.should be == '0001.txt'
115
+ end
116
+ end
117
+
118
+ describe '#number_for' do
119
+ it 'returns number for file' do
120
+ inside test_dir do
121
+ touch 'av023cd.txt'
122
+ end
123
+
124
+ dir = Nrename::Directory.new test_dir
125
+ file = dir.numbered_files.first
126
+ dir.number_for(file).should be == 23
127
+ end
128
+ end
129
+
130
+ describe '#adjusted_number_string_for' do
131
+ it 'returns number string adjusted to field length' do
132
+ inside test_dir do
133
+ touch 'qwe0032rty.gif'
134
+ end
135
+
136
+ dir = Nrename::Directory.new test_dir
137
+ dir.stub num_field_length: 6
138
+ file = dir.numbered_files.first
139
+ dir.adjusted_number_string_for(file).should be == '000032'
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nrename::Options do
4
+ def parse_options(args)
5
+ Nrename::Options.parse args
6
+ end
7
+
8
+ describe 'verbosity' do
9
+ it 'is on by default (when no arguments provided)' do
10
+ parse_options([]).verbose.should be_true
11
+ end
12
+
13
+ it 'is off when or "--no-verbose" switch is provided' do
14
+ parse_options(%w[--no-verbose]).verbose.should be_false
15
+ end
16
+ end
17
+
18
+ describe 'recursive processing' do
19
+ it 'is off by default' do
20
+ parse_options([]).recursive.should be_false
21
+ end
22
+
23
+ it 'is on when "-R" of "--recursive" is provided' do
24
+ %w[-R --recursive].each do |option|
25
+ parse_options([option]).recursive.should be_true
26
+ end
27
+ end
28
+ end
29
+
30
+ describe 'directory arguments' do
31
+ let(:test_dir) { File.expand_path 'test_dir' }
32
+ let(:subdirs) { %w[aa bb cc] }
33
+
34
+ before :all do
35
+ inside test_dir do
36
+ mkdir subdirs
37
+ end
38
+ end
39
+
40
+ after :all do
41
+ rm_rf test_dir
42
+ end
43
+
44
+ it 'captures rest of arguments as directories to process' do
45
+ subdirs.each do |subdir|
46
+ subdir_path = File.expand_path subdir, test_dir
47
+ arg = File.join test_dir, subdir
48
+ parse_options([arg]).dirs.should include subdir_path
49
+ end
50
+ end
51
+
52
+ it 'captures current dir if no arguments provided' do
53
+ parse_options([]).dirs.should be == [File.expand_path('.')]
54
+ end
55
+
56
+ it 'recursively captures all subdirs when -R option provided' do
57
+ dirs = parse_options(['-R', test_dir]).dirs
58
+
59
+ dirs.should include test_dir
60
+
61
+ subdirs.each do |subdir|
62
+ dirs.should include File.join(test_dir, subdir)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,16 @@
1
+ require 'rspec'
2
+ require 'fileutils'
3
+
4
+ require File.expand_path '../../lib/nrename', __FILE__
5
+
6
+ module Support
7
+ def inside(dir, &block)
8
+ mkdir dir unless File.exists? dir
9
+ cd dir, &block
10
+ end
11
+ end
12
+
13
+ RSpec.configure do |config|
14
+ config.include FileUtils
15
+ config.include Support
16
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nrename
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Victor Deryagin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &81769620 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *81769620
25
+ - !ruby/object:Gem::Dependency
26
+ name: aruba
27
+ requirement: &81769410 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *81769410
36
+ description: ''
37
+ email:
38
+ - vderyagin@gmail.com
39
+ executables:
40
+ - nrename
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - bin/nrename
45
+ - lib/nrename/options.rb
46
+ - lib/nrename/version.rb
47
+ - lib/nrename/directory.rb
48
+ - lib/nrename.rb
49
+ - spec/spec_helper.rb
50
+ - spec/nrename/options_spec.rb
51
+ - spec/nrename/directory_spec.rb
52
+ - features/renaming_files.feature
53
+ - features/support/env.rb
54
+ - features/options_processing.feature
55
+ homepage: ''
56
+ licenses: []
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project: nrename
75
+ rubygems_version: 1.8.10
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: ''
79
+ test_files:
80
+ - spec/spec_helper.rb
81
+ - spec/nrename/options_spec.rb
82
+ - spec/nrename/directory_spec.rb
83
+ - features/renaming_files.feature
84
+ - features/support/env.rb
85
+ - features/options_processing.feature
86
+ has_rdoc: