filerenamer 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/bin/classifyWith1stChar +124 -0
- data/bin/filenameNumber +34 -0
- data/bin/filenameRegulate +80 -0
- data/bin/renamer +27 -0
- data/filerenamer.gemspec +74 -0
- data/lib/filerenamer.rb +0 -0
- data/lib/filerenamer/filerenamer.rb +252 -0
- data/lib/filerenamer/filerenameroptionparser.rb +36 -0
- data/test/filerenamer/a0.txt +0 -0
- data/test/filerenamer/dummy.txt +0 -0
- data/test/helper.rb +17 -0
- data/test/test_filerenamer.rb +404 -0
- data/test/test_filerenameroptionparser.rb +53 -0
- metadata +140 -0
data/lib/filerenamer.rb
ADDED
File without changes
|
@@ -0,0 +1,252 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
require "fileutils"
|
5
|
+
require "optparse"
|
6
|
+
require "filerenamer/filerenameroptionparser.rb"
|
7
|
+
|
8
|
+
require "rubygems"
|
9
|
+
gem "builtinextension"
|
10
|
+
require "string_escape_zsh.rb"
|
11
|
+
require "string_width.rb"
|
12
|
+
|
13
|
+
class FileRenamerNoRenameRuleError < Exception; end
|
14
|
+
class FileRenamerOptionError < Exception; end
|
15
|
+
|
16
|
+
# ファイル群の名前変更を一括して行うためのクラス。
|
17
|
+
#
|
18
|
+
# MEMO:
|
19
|
+
# 一度 temporary directory にリネームして格納し、
|
20
|
+
# これをカレントディレクトリからのパスに移動する形を取ると、
|
21
|
+
# ディレクトリをまたぐリネームが非常に面倒なことになる。
|
22
|
+
# - 他のリネームに依存する場合に順序問題。
|
23
|
+
# - 相互依存のデッドロック
|
24
|
+
# gem などで提供される temporary directory は
|
25
|
+
# 基本的に 抜けたときに削除される筈なので、
|
26
|
+
# 途中まで変換してから interrupt されたときに
|
27
|
+
# 中にあるファイルごと消される可能性がありそう。
|
28
|
+
# そのため、メソッド内で自分で temporary directory を作成する。
|
29
|
+
#
|
30
|
+
# 没案
|
31
|
+
# rename_rule メソッドをデフォルトで例外にしておいて、
|
32
|
+
# コマンドスクリプト側で定義するという方法は、
|
33
|
+
# メソッドの引数で ArgumentError のもとになり、
|
34
|
+
# 自由度が少なくなる。
|
35
|
+
# たとえば old_str, new_str を渡したい時と、
|
36
|
+
# 更新時刻でリネームしたいときでは必要な引数の数が異なる。
|
37
|
+
class FileRenamer
|
38
|
+
|
39
|
+
#:yes と :no が両方 true ならば例外。
|
40
|
+
#:copy, :move, :hardlink, :symlink のうち、1つ以下が true。
|
41
|
+
#全て nil ならば :move が true になる。
|
42
|
+
#:quiet が true ならば自動的に :yes が立てられる。
|
43
|
+
#:quiet が true で :no も true ならば例外。
|
44
|
+
def initialize(options)
|
45
|
+
@options = options
|
46
|
+
|
47
|
+
if (@options[:yes] && @options[:no])
|
48
|
+
raise FileRenamerOptionError,
|
49
|
+
"Conflict options: --yes and --no."
|
50
|
+
end
|
51
|
+
|
52
|
+
fileProcessModes = []
|
53
|
+
[:move, :copy, :hardlink, :symlink].each do |mode|
|
54
|
+
fileProcessModes << mode if @options[mode]
|
55
|
+
end
|
56
|
+
# 1つもなければ :move に。
|
57
|
+
@options[:move] = true if fileProcessModes == []
|
58
|
+
# 2つ以上あれば例外。
|
59
|
+
if fileProcessModes.size > 1
|
60
|
+
raise FileRenamerOptionError,
|
61
|
+
"File process modes duplicate: #{fileProcessModes.join(", ")}"
|
62
|
+
end
|
63
|
+
@command = "mv" if @options[:move]
|
64
|
+
@command = "cp -r" if @options[:copy]
|
65
|
+
@command = "ln" if @options[:hardlink]
|
66
|
+
@command = "ln -s" if @options[:symlink]
|
67
|
+
|
68
|
+
# :quiet ならば自動的に :yes
|
69
|
+
@options[:yes] = true if @options[:quiet]
|
70
|
+
|
71
|
+
# :quiet と同時に :no なら例外
|
72
|
+
if @options[:quiet] && @options[:no]
|
73
|
+
raise FileRenamerOptionError,
|
74
|
+
"Conflict options: --quiet and --no"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# 変更される名前のリストを表示し、ユーザの指示に従って実行する。
|
79
|
+
# ユーザの入力は [y|Y] で始まる文字列ならば実行、
|
80
|
+
# それ以外なら実行しない。
|
81
|
+
# files は対象のファイル名のリスト。
|
82
|
+
# 新しい名前の生成方法をブロックで渡す。
|
83
|
+
# ブロックがなければ例外 FileRenamerNoRenameRuleError
|
84
|
+
def execute(files, &block)
|
85
|
+
files = Dir::glob("*").sort if files.empty?
|
86
|
+
|
87
|
+
new_names = make_new_names(files, &block)
|
88
|
+
|
89
|
+
ok_files, ng_files = check_new_names(new_names)
|
90
|
+
|
91
|
+
unless @options[:quiet]
|
92
|
+
if ok_files.size > 0
|
93
|
+
puts "Enable files:"
|
94
|
+
max_width = ok_files.keys.max_by{|file| file.width}.width
|
95
|
+
ok_files.keys.sort.each do |old|
|
96
|
+
printf(" %s %s%s %s\n",
|
97
|
+
@command, old, " " * (max_width - old.width), ok_files[old]
|
98
|
+
)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
if ng_files.size > 0
|
103
|
+
puts "Unable files:"
|
104
|
+
max_width = ng_files.keys.max_by{|file| file.width}.width
|
105
|
+
ng_files.keys.sort.each do |old|
|
106
|
+
printf(" %s %s%s %s\n",
|
107
|
+
@command, old, " " * (max_width - old.width), ng_files[old]
|
108
|
+
)
|
109
|
+
end
|
110
|
+
puts
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
if ok_files.empty?
|
115
|
+
puts "Done. No executable files." unless @options[:quiet]
|
116
|
+
return
|
117
|
+
elsif @options[:no]
|
118
|
+
puts "Execute? no"
|
119
|
+
return
|
120
|
+
end
|
121
|
+
|
122
|
+
if @options[:yes]
|
123
|
+
puts "Execute? yes" unless @options[:quiet]
|
124
|
+
elsif (! ask_yes?)
|
125
|
+
return
|
126
|
+
end
|
127
|
+
ok_files.each do |old, new|
|
128
|
+
run(old, new)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def make_new_names(files, &block)
|
135
|
+
results = {}
|
136
|
+
files.each { |i| results[i] = yield i }
|
137
|
+
return results
|
138
|
+
end
|
139
|
+
|
140
|
+
# 新しい名前リストを受け取り、問題なくリネームできるものと
|
141
|
+
# できないものを選別する。
|
142
|
+
# OK, NG の順に2つの配列を返す。
|
143
|
+
#
|
144
|
+
# 判断基準は、以下の AND 条件。
|
145
|
+
# - 新しい名前が古い名前リストに含まれないこと。
|
146
|
+
# - 新しい名前が新しい名前リストに1つ(自分)のみしかないこと。
|
147
|
+
# - 新しい名前のファイルが既に存在しないこと。
|
148
|
+
#
|
149
|
+
# 没案
|
150
|
+
# 新しい名前が変換されない古い名前であれば、
|
151
|
+
# これも NG リストに追加する。(表示用)
|
152
|
+
# このルールにすると、変換に順序依存が生じる可能性があり、
|
153
|
+
# temporary directory を経由する必要ができる。
|
154
|
+
# その結果、リネーム過程で深い temporary directory を
|
155
|
+
# 作成したり削除したりしなければならなくなる。
|
156
|
+
def check_new_names(old_new_hash)
|
157
|
+
ok_files = {}
|
158
|
+
ng_files = {}
|
159
|
+
|
160
|
+
old_new_hash.each do |old, new|
|
161
|
+
# 変化がない場合はスルー
|
162
|
+
next if old == new
|
163
|
+
|
164
|
+
# 新しい名前に nil が定義されていてもスルー
|
165
|
+
next if new == nil
|
166
|
+
|
167
|
+
# 既に存在していれば、既に存在するファイルごと NG に登録。
|
168
|
+
if FileTest.exist?(new)
|
169
|
+
ng_files[old] = new
|
170
|
+
ng_files[new] = new
|
171
|
+
next
|
172
|
+
end
|
173
|
+
|
174
|
+
# new が複数 重複していれば、 NG。
|
175
|
+
if (old_new_hash.values.select{|name| name == new}.size > 1)
|
176
|
+
ng_files[old] = new
|
177
|
+
next
|
178
|
+
end
|
179
|
+
|
180
|
+
# new が old に含まれていれば、NG。
|
181
|
+
if (old_new_hash.keys.include?(new))
|
182
|
+
ng_files[old] = new
|
183
|
+
next
|
184
|
+
end
|
185
|
+
|
186
|
+
# 上記以外の場合ならば OK
|
187
|
+
|
188
|
+
ok_files[old] = new
|
189
|
+
end
|
190
|
+
return ok_files, ng_files
|
191
|
+
end
|
192
|
+
|
193
|
+
# ユーザに判断を求める。
|
194
|
+
# 標準入力から文字列を受け取り、
|
195
|
+
# [y|Y] から始まる文字列なら true を、
|
196
|
+
# それ以外なら false を返す。
|
197
|
+
def ask_yes?
|
198
|
+
puts "Execute?"
|
199
|
+
str = $stdin.gets
|
200
|
+
if /^y/i =~ str
|
201
|
+
return true
|
202
|
+
else
|
203
|
+
return false
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# コマンドを表示しつつ実行。
|
208
|
+
# 既にファイルチェックされているはずなので、チェックはしない。
|
209
|
+
# 少なくとも当面は。
|
210
|
+
# ディレクトリが必要ならここで作成。
|
211
|
+
# ディレクトリが不要になればここで削除。
|
212
|
+
# 本来ここでない方が分かり易い気もするのだが、ここに追加するのが一番簡単なので。
|
213
|
+
def run(old, new)
|
214
|
+
# 変換先のディレクトリがなければ生成
|
215
|
+
#pp old, new; exit
|
216
|
+
paths(new).each do |directory|
|
217
|
+
unless FileTest.exist?(directory)
|
218
|
+
puts " make directory: #{directory}" unless @options[:quiet]
|
219
|
+
FileUtils.mkdir_p(directory)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# 変換の実行
|
224
|
+
command = " #{@command} #{old.escape_zsh} #{new.escape_zsh}"
|
225
|
+
puts command unless @options[:quiet]
|
226
|
+
system(command)
|
227
|
+
|
228
|
+
# 変換元のディレクトリが空になっていれば削除
|
229
|
+
dirs = paths(old)
|
230
|
+
dirs.reverse.each do |directory|
|
231
|
+
if Dir.entries(directory).size == 2 # . と .. のみ
|
232
|
+
puts " remove directory: #{directory}" unless @options[:quiet]
|
233
|
+
Dir.rmdir(directory)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# パスに含まれるディレクトリ名を、階層ごとに切り分けたソート済配列にして返す。
|
239
|
+
# 最後の要素は含まない。
|
240
|
+
# e.g. foo/bar/baz.txt => ["foo", "foo/bar"]
|
241
|
+
# e.g. /foo/bar/baz.txt => ["/foo", "foo/bar"]
|
242
|
+
def paths(path)
|
243
|
+
dirs = path.split("/")
|
244
|
+
results = []
|
245
|
+
(dirs.size - 1).times do |i|
|
246
|
+
results << dirs[0..i].join("/")
|
247
|
+
end
|
248
|
+
results.delete_at(0) if results[0] == ""
|
249
|
+
return results
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
require "optparse"
|
5
|
+
|
6
|
+
# FileRenamer 用のオプション解析器。
|
7
|
+
# ユーザはこれに任意のオプションを追加できる。
|
8
|
+
#
|
9
|
+
# 通常の OptionParser と異なり、インスタンス変数 @options に情報を格納する。
|
10
|
+
# @options は attr_reader に指定されているので、外部から読み取れる。
|
11
|
+
# @options は Hash であるので、ユーザが on で追加するブロックで
|
12
|
+
# そのまま鍵と値を追加できる。
|
13
|
+
# また、@options に追加せずに自前で何か適当な処理をしても良い。
|
14
|
+
class FileRenamerOptionParser < OptionParser
|
15
|
+
|
16
|
+
attr_reader :options
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@options = {}
|
20
|
+
super
|
21
|
+
on("-y", "--yes" , "Yes for all questions."){@options[:yes] = true}
|
22
|
+
on("-n", "--no" , "No for all questions."){@options[:no] = true}
|
23
|
+
on("-c", "--copy" , "Copy mode." ){@options[:copy] = true}
|
24
|
+
on("-m", "--move" , "Move mode.(default)" ){@options[:move] = true}
|
25
|
+
on("-h", "--hardlink", "Hardlink mode." ){@options[:hardlink]= true}
|
26
|
+
on("-s", "--symlink" , "Symlink mode." ){@options[:symlink] = true}
|
27
|
+
on("-q", "--quiet" , "Quiet mode. Forced non-interactive."){
|
28
|
+
@options[:quiet] = true
|
29
|
+
#このオプションが設定されているときは強制的に --yes として扱われる。
|
30
|
+
#non_interactive_mode になる。
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
File without changes
|
File without changes
|
data/test/helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
require 'filerenamer'
|
15
|
+
|
16
|
+
class Test::Unit::TestCase
|
17
|
+
end
|
@@ -0,0 +1,404 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
require 'helper'
|
5
|
+
|
6
|
+
require "test/unit"
|
7
|
+
require "filerenamer/filerenamer.rb"
|
8
|
+
require "stringio"
|
9
|
+
require "rubygems"
|
10
|
+
gem "capture_stdout"
|
11
|
+
require "capture_stdout"
|
12
|
+
|
13
|
+
class FileRenamer
|
14
|
+
public :check_new_names
|
15
|
+
public :ask_yes?
|
16
|
+
public :run
|
17
|
+
public :make_new_names
|
18
|
+
public :paths
|
19
|
+
attr_reader :options
|
20
|
+
end
|
21
|
+
|
22
|
+
class TC_FileRenamer < Test::Unit::TestCase
|
23
|
+
EXIST_FILE = "test/filerenamer/dummy.txt"
|
24
|
+
|
25
|
+
A_0 = "test/filerenamer/a0.txt"
|
26
|
+
A_1 = "test/filerenamer/a1.txt"
|
27
|
+
|
28
|
+
def setup
|
29
|
+
options = {}
|
30
|
+
@fr00 = FileRenamer.new(options)
|
31
|
+
|
32
|
+
options = {:copy => true, :yes => true}
|
33
|
+
@fr01 = FileRenamer.new(options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_initialize
|
37
|
+
# yes and no
|
38
|
+
options = {
|
39
|
+
:yes => true,
|
40
|
+
:no => true,
|
41
|
+
}
|
42
|
+
assert_raise(FileRenamerOptionError){ FileRenamer.new(options) }
|
43
|
+
|
44
|
+
# ファイル操作モードがどれか1つのみ true なら OK。
|
45
|
+
options = { :copy => true, }
|
46
|
+
assert_nothing_raised{ FileRenamer.new(options) }
|
47
|
+
|
48
|
+
options = { :move => true, }
|
49
|
+
assert_nothing_raised{ FileRenamer.new(options) }
|
50
|
+
|
51
|
+
options = { :hardlink => true, }
|
52
|
+
assert_nothing_raised{ FileRenamer.new(options) }
|
53
|
+
|
54
|
+
options = { :symlink => true, }
|
55
|
+
assert_nothing_raised{ FileRenamer.new(options) }
|
56
|
+
|
57
|
+
# ファイル操作モードが空でも OK で、その場合は :move が true として扱われる。
|
58
|
+
options = { }
|
59
|
+
fr00 = FileRenamer.new(options)
|
60
|
+
assert_equal( {:move => true}, fr00.options )
|
61
|
+
|
62
|
+
# ファイル操作モードで矛盾する2つ以上が true なら例外。
|
63
|
+
options = {
|
64
|
+
:move => true,
|
65
|
+
:copy => true,
|
66
|
+
}
|
67
|
+
assert_raise(FileRenamerOptionError){ FileRenamer.new(options) }
|
68
|
+
|
69
|
+
options = {
|
70
|
+
:move => true,
|
71
|
+
:hardlink => true,
|
72
|
+
}
|
73
|
+
assert_raise(FileRenamerOptionError){ FileRenamer.new(options) }
|
74
|
+
|
75
|
+
options = {
|
76
|
+
:move => true,
|
77
|
+
:symlink => true,
|
78
|
+
}
|
79
|
+
assert_raise(FileRenamerOptionError){ FileRenamer.new(options) }
|
80
|
+
|
81
|
+
# :quiet が立てられれば、自動的に :yes も true になる。
|
82
|
+
options = {:quiet => true}
|
83
|
+
fr00 = FileRenamer.new(options)
|
84
|
+
assert_equal( {:quiet => true, :yes => true, :move => true}, fr00.options )
|
85
|
+
|
86
|
+
# :quiet が立てられれば、:yes が明示的に立っていても問題なし。
|
87
|
+
options = {:quiet => true, :yes => true}
|
88
|
+
fr00 = FileRenamer.new(options)
|
89
|
+
assert_equal( {:quiet => true, :yes => true, :move => true}, fr00.options )
|
90
|
+
|
91
|
+
# :quiet が立てられれば、:no が立っていれば例外。
|
92
|
+
options = {:quiet => true, :no => true}
|
93
|
+
assert_raise(FileRenamerOptionError){ FileRenamer.new(options) }
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_execute
|
97
|
+
# :yes
|
98
|
+
# pre-process
|
99
|
+
FileUtils.rm(A_1) if FileTest.exist?(A_1)
|
100
|
+
#
|
101
|
+
options = {:copy => true, :yes => true}
|
102
|
+
fr01 = FileRenamer.new(options)
|
103
|
+
str = capture_stdout{fr01.execute([A_0]){ A_1 }}
|
104
|
+
assert_equal(true, FileTest.exist?(A_0))
|
105
|
+
assert_equal(true, FileTest.exist?(A_1))
|
106
|
+
FileUtils.rm(A_1)
|
107
|
+
#
|
108
|
+
correct =
|
109
|
+
"Enable files:\n" +
|
110
|
+
" cp -r #{A_0} #{A_1}\n" +
|
111
|
+
"Execute? yes\n" +
|
112
|
+
" cp -r #{A_0} #{A_1}\n"
|
113
|
+
t = str
|
114
|
+
assert_equal(correct[0], t[0])
|
115
|
+
assert_equal(correct[1], t[1])
|
116
|
+
assert_equal(correct[2], t[2])
|
117
|
+
assert_equal(correct[3], t[3])
|
118
|
+
assert_equal(correct[4], t[4])
|
119
|
+
|
120
|
+
# :no
|
121
|
+
FileUtils.rm(A_1) if FileTest.exist?(A_1)
|
122
|
+
#
|
123
|
+
options = {:copy => true, :no => true}
|
124
|
+
fr01 = FileRenamer.new(options)
|
125
|
+
str = capture_stdout{ fr01.execute([A_0]){ A_1 }}
|
126
|
+
assert_equal(true , FileTest.exist?(A_0))
|
127
|
+
assert_equal(false, FileTest.exist?(A_1))
|
128
|
+
#
|
129
|
+
correct =
|
130
|
+
"Enable files:\n" +
|
131
|
+
" cp -r #{A_0} #{A_1}\n" +
|
132
|
+
"Execute? no\n"
|
133
|
+
t = str
|
134
|
+
assert_equal(correct[0], t[0])
|
135
|
+
assert_equal(correct[1], t[1])
|
136
|
+
assert_equal(correct[2], t[2])
|
137
|
+
|
138
|
+
#:quiet
|
139
|
+
FileUtils.rm(A_1) if FileTest.exist?(A_1)
|
140
|
+
io = StringIO.new
|
141
|
+
#
|
142
|
+
options = {:copy => true, :quiet => true}
|
143
|
+
fr01 = FileRenamer.new(options)
|
144
|
+
str = capture_stdout{fr01.execute([A_0]){ A_1 }}
|
145
|
+
assert_equal(true, FileTest.exist?(A_0))
|
146
|
+
assert_equal(true, FileTest.exist?(A_1))
|
147
|
+
FileUtils.rm(A_1)
|
148
|
+
#
|
149
|
+
assert_equal( "", str)
|
150
|
+
|
151
|
+
#ask
|
152
|
+
FileUtils.rm(A_1) if FileTest.exist?(A_1)
|
153
|
+
$stdin = StringIO.new
|
154
|
+
$stdin.puts "yes"
|
155
|
+
$stdin.rewind
|
156
|
+
output = StringIO.new
|
157
|
+
#
|
158
|
+
options = {:copy => true}
|
159
|
+
fr01 = FileRenamer.new(options)
|
160
|
+
str = capture_stdout{fr01.execute([A_0]){ A_1 }}
|
161
|
+
assert_equal(true, FileTest.exist?(A_0))
|
162
|
+
assert_equal(true, FileTest.exist?(A_1))
|
163
|
+
FileUtils.rm(A_1)
|
164
|
+
#
|
165
|
+
correct =
|
166
|
+
"Enable files:\n" +
|
167
|
+
" cp -r #{A_0} #{A_1}\n" +
|
168
|
+
"Execute?\n" +
|
169
|
+
" cp -r #{A_0} #{A_1}\n"
|
170
|
+
t = str
|
171
|
+
assert_equal(correct[0], t[0])
|
172
|
+
assert_equal(correct[1], t[1])
|
173
|
+
assert_equal(correct[2], t[2])
|
174
|
+
assert_equal(correct[3], t[3])
|
175
|
+
|
176
|
+
$stdin = STDIN
|
177
|
+
|
178
|
+
#ask
|
179
|
+
#NG ファイルが存在するときの表示
|
180
|
+
FileUtils.rm(A_1) if FileTest.exist?(A_1)
|
181
|
+
$stdin = StringIO.new
|
182
|
+
$stdin.puts "yes"
|
183
|
+
$stdin.rewind
|
184
|
+
output = StringIO.new
|
185
|
+
#
|
186
|
+
options = {:copy => true}
|
187
|
+
fr01 = FileRenamer.new(options)
|
188
|
+
str = capture_stdout{fr01.execute([A_1]){ A_0 }}
|
189
|
+
assert_equal(true , FileTest.exist?(A_0))
|
190
|
+
assert_equal(false, FileTest.exist?(A_1))
|
191
|
+
#
|
192
|
+
correct =
|
193
|
+
"Unable files:\n" +
|
194
|
+
" cp -r #{A_0} #{A_0}\n" +
|
195
|
+
" cp -r #{A_1} #{A_0}\n" +
|
196
|
+
"\n" +
|
197
|
+
"Done. No executable files.\n"
|
198
|
+
t = str
|
199
|
+
assert_equal(correct[0], t[0])
|
200
|
+
assert_equal(correct[1], t[1])
|
201
|
+
assert_equal(correct[2], t[2])
|
202
|
+
assert_equal(correct[3], t[3])
|
203
|
+
assert_equal(correct[4], t[4])
|
204
|
+
$stdin = STDIN
|
205
|
+
|
206
|
+
## ファイルリストを与えないときはカレントディレクトリの全ファイルが対象。
|
207
|
+
#FileUtils.rm(A_1) if FileTest.exist?(A_1)
|
208
|
+
##
|
209
|
+
#options = {:copy => true, :no => true}
|
210
|
+
#fr01 = FileRenamer.new(options)
|
211
|
+
#str = capture_stdout{ fr01.execute([]){|name| name + ".00"}}
|
212
|
+
##
|
213
|
+
#correct =
|
214
|
+
# "Enable files:\n" +
|
215
|
+
# " cp -r Gemfile Gemfile.00\n" +
|
216
|
+
# " cp -r Gemfile.lock Gemfile.lock.00\n" +
|
217
|
+
# " cp -r LICENSE.txt LICENSE.txt.00\n" +
|
218
|
+
# " cp -r README.rdoc README.rdoc.00\n" +
|
219
|
+
# " cp -r Rakefile Rakefile.00\n" +
|
220
|
+
# " cp -r VERSION VERSION.00\n" +
|
221
|
+
# " cp -r lib lib.00\n" +
|
222
|
+
# " cp -r test test.00\n" +
|
223
|
+
# "Execute? no\n"
|
224
|
+
#assert_equal( correct, str)
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_make_new_names
|
228
|
+
assert_equal(
|
229
|
+
{
|
230
|
+
A_0 => A_0 + "00",
|
231
|
+
A_1 => A_1 + "00",
|
232
|
+
},
|
233
|
+
@fr00.make_new_names([A_0, A_1]){ |old|
|
234
|
+
old.sub(/$/, "00")
|
235
|
+
}
|
236
|
+
)
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_check_new_names
|
240
|
+
files = {
|
241
|
+
"alice.txt" => EXIST_FILE,
|
242
|
+
"bcdefgh.txt" => EXIST_FILE,
|
243
|
+
"charly.txt" => "C.txt",
|
244
|
+
"david.txt" => "D.txt",
|
245
|
+
EXIST_FILE => EXIST_FILE,
|
246
|
+
"eva.txt" => "alice.txt",
|
247
|
+
"f.txt" => "f.txt",
|
248
|
+
"g.txt" => nil,
|
249
|
+
}
|
250
|
+
ok_list, ng_list = @fr00.check_new_names(files)
|
251
|
+
assert_equal(
|
252
|
+
{ "charly.txt" => "C.txt",
|
253
|
+
"david.txt" => "D.txt",
|
254
|
+
},
|
255
|
+
ok_list
|
256
|
+
)
|
257
|
+
assert_equal(
|
258
|
+
{ "alice.txt" => EXIST_FILE,
|
259
|
+
"bcdefgh.txt" => EXIST_FILE,
|
260
|
+
EXIST_FILE => EXIST_FILE,
|
261
|
+
"eva.txt" => "alice.txt",
|
262
|
+
},
|
263
|
+
ng_list
|
264
|
+
)
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_ask_yes?
|
269
|
+
$stdin = StringIO.new
|
270
|
+
$stdin.puts "Y"
|
271
|
+
$stdin.rewind
|
272
|
+
result = Object.new
|
273
|
+
str = capture_stdout{ result = @fr00.ask_yes?}
|
274
|
+
assert_equal(true , result)
|
275
|
+
assert_equal("Execute?\n" , str)
|
276
|
+
|
277
|
+
$stdin = StringIO.new
|
278
|
+
$stdin.puts "y"
|
279
|
+
$stdin.rewind
|
280
|
+
io = capture_stdout{ result = @fr00.ask_yes?}
|
281
|
+
assert_equal(true , result)
|
282
|
+
|
283
|
+
$stdin = StringIO.new
|
284
|
+
$stdin.puts "Yreqwj"
|
285
|
+
$stdin.rewind
|
286
|
+
io = capture_stdout{ result = @fr00.ask_yes?}
|
287
|
+
assert_equal(true , result)
|
288
|
+
|
289
|
+
$stdin = StringIO.new
|
290
|
+
$stdin.puts "yrqewv"
|
291
|
+
$stdin.rewind
|
292
|
+
io = capture_stdout{ result = @fr00.ask_yes?}
|
293
|
+
assert_equal(true , result)
|
294
|
+
|
295
|
+
$stdin = StringIO.new
|
296
|
+
$stdin.puts "n"
|
297
|
+
$stdin.rewind
|
298
|
+
io = capture_stdout{ result = @fr00.ask_yes?}
|
299
|
+
assert_equal(false, result)
|
300
|
+
|
301
|
+
$stdin = StringIO.new
|
302
|
+
$stdin.puts "N"
|
303
|
+
$stdin.rewind
|
304
|
+
io = capture_stdout{ result = @fr00.ask_yes?}
|
305
|
+
assert_equal(false, result)
|
306
|
+
|
307
|
+
$stdin = StringIO.new
|
308
|
+
$stdin.puts ""
|
309
|
+
$stdin.rewind
|
310
|
+
io = capture_stdout{ result = @fr00.ask_yes?}
|
311
|
+
assert_equal(false, result)
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_run
|
315
|
+
# # ディレクトリ管理不要の場合
|
316
|
+
# FileUtils.rm(A_1) if FileTest.exist?(A_1)
|
317
|
+
# #
|
318
|
+
# @fr01.run(A_0, A_1)
|
319
|
+
# io = capture_stdout{ @fr01.run(A_0, A_1) }
|
320
|
+
# io.rewind
|
321
|
+
# assert_equal([" cp -r #{A_0} #{A_1}\n"], io.readlines)
|
322
|
+
# #
|
323
|
+
# assert_equal(true, FileTest.exist?(A_0))
|
324
|
+
# assert_equal(true, FileTest.exist?(A_1))
|
325
|
+
# #
|
326
|
+
# # あとかたづけ
|
327
|
+
# FileUtils.rm(A_1)
|
328
|
+
#
|
329
|
+
# # ディレクトリ生成が必要な場合
|
330
|
+
# FileUtils.rm("tmp/#{A_1}") if FileTest.exist?("tmp/#{A_1}")
|
331
|
+
# FileUtils.rmdir("tmp/test/FileRenamer") if FileTest.exist?("tmp/test/FileRenamer")
|
332
|
+
# FileUtils.rmdir("tmp/test") if FileTest.exist?("tmp/test")
|
333
|
+
# FileUtils.rmdir("tmp") if FileTest.exist?("tmp")
|
334
|
+
# #
|
335
|
+
# io = capture_stdout{ @fr01.run(A_0, "tmp/"+A_1) }
|
336
|
+
# io.rewind
|
337
|
+
# t = io.readlines
|
338
|
+
# assert_equal(" make directory: tmp\n", t[0])
|
339
|
+
# assert_equal(" make directory: tmp/test\n", t[1])
|
340
|
+
# assert_equal(" make directory: tmp/test/FileRenamer\n", t[2])
|
341
|
+
# assert_equal(" cp -r #{A_0} tmp/#{A_1}\n", t[3])
|
342
|
+
# assert_equal(4, t.size)
|
343
|
+
# #
|
344
|
+
# assert_equal(true, FileTest.exist?(A_0))
|
345
|
+
# assert_equal(true, FileTest.exist?("tmp/#{A_1}"))
|
346
|
+
# assert_equal(true, FileTest.exist?("tmp/test/FileRenamer"))
|
347
|
+
# assert_equal(true, FileTest.exist?("tmp/test" ))
|
348
|
+
# assert_equal(true, FileTest.exist?("tmp" ))
|
349
|
+
# #
|
350
|
+
# # あとかたづけ
|
351
|
+
# FileUtils.rm("tmp/#{A_1}")
|
352
|
+
# FileUtils.rmdir("tmp/test/FileRenamer")
|
353
|
+
# FileUtils.rmdir("tmp/test" )
|
354
|
+
# FileUtils.rmdir("tmp" )
|
355
|
+
|
356
|
+
# ディレクトリ消去が必要な場合
|
357
|
+
FileUtils.rm("tmp1/dir/a1.txt") if FileTest.exist?("tmp1/dir/a1.txt")
|
358
|
+
FileUtils.rm("tmp2/dir/a1.txt") if FileTest.exist?("tmp2/dir/a1.txt")
|
359
|
+
FileUtils.rmdir("tmp1/dir") if FileTest.exist?("tmp1")
|
360
|
+
FileUtils.rmdir("tmp2/dir") if FileTest.exist?("tmp2")
|
361
|
+
FileUtils.rmdir("tmp1") if FileTest.exist?("tmp1")
|
362
|
+
FileUtils.rmdir("tmp2") if FileTest.exist?("tmp2")
|
363
|
+
#
|
364
|
+
FileUtils.mkdir("tmp1")
|
365
|
+
FileUtils.mkdir("tmp1/dir")
|
366
|
+
FileUtils.cp(A_0, "tmp1/dir/a1.txt")
|
367
|
+
#
|
368
|
+
assert_equal(false, FileTest.exist?("tmp2/dir/a2")) #実行前に変換先が存在しないことを確認。
|
369
|
+
#@fr00.run("tmp1/dir/a1.txt", "tmp2/dir/a1.txt")
|
370
|
+
str = capture_stdout{ @fr00.run("tmp1/dir/a1.txt", "tmp2/dir/a1.txt") }
|
371
|
+
t = str
|
372
|
+
correct = " make directory: tmp2\n" +
|
373
|
+
" make directory: tmp2/dir\n" +
|
374
|
+
" mv tmp1/dir/a1.txt tmp2/dir/a1.txt\n" +
|
375
|
+
" remove directory: tmp1/dir\n" +
|
376
|
+
" remove directory: tmp1\n"
|
377
|
+
assert_equal(correct, t)
|
378
|
+
#
|
379
|
+
assert_equal(false, FileTest.exist?("tmp1"))
|
380
|
+
assert_equal(true , FileTest.exist?("tmp2/dir/a1.txt")) #実行後に変換先が存在することを確認。
|
381
|
+
#
|
382
|
+
# あとかたづけ
|
383
|
+
FileUtils.rmdir("tmp1/dir")
|
384
|
+
FileUtils.rmdir("tmp1")
|
385
|
+
FileUtils.rm("tmp2/dir/a1.txt")
|
386
|
+
FileUtils.rmdir("tmp2/dir")
|
387
|
+
FileUtils.rmdir("tmp2")
|
388
|
+
end
|
389
|
+
|
390
|
+
def test_paths
|
391
|
+
assert_equal(["foo", "foo/bar"], @fr00.paths("foo/bar/baz.txt"))
|
392
|
+
assert_equal([], @fr00.paths("baz.txt"))
|
393
|
+
assert_equal(["/foo", "/foo/bar"], @fr00.paths("/foo/bar/baz.txt"))
|
394
|
+
end
|
395
|
+
|
396
|
+
#undef test_initialize
|
397
|
+
#undef test_make_new_names
|
398
|
+
#undef test_check_new_names
|
399
|
+
#undef test_ask_yes?
|
400
|
+
#undef test_execute
|
401
|
+
#undef test_run
|
402
|
+
|
403
|
+
end
|
404
|
+
|