names_to_numbers.rb: add "preserve names" option
[cmccabe-bin] / names_to_numbers.rb
1 #!/usr/bin/ruby -w
2
3 #
4 # names_to_numbers.rb
5 #
6 # Renames all the files in a directory with the given file extension.
7 # The renamed files will just have numbers.
8 #
9 # Colin Mccabe
10 #
11
12 require 'fileutils'
13 require 'optparse'
14 require 'ostruct'
15
16 class MyOptions
17   def self.parse(args)
18     opts = OpenStruct.new
19     opts.dry_run = false
20     opts.num_digits = 2
21     opts.extension = nil
22     $fu_args = { :verbose => true }
23     opts.preserve_names = false
24
25     # Fill in $opts values
26     parser = OptionParser.new do |myparser|
27       myparser.banner = "Usage: #{ File.basename($0) } [opts]"
28       myparser.separator("Specific options:")
29       myparser.on("--num-digits DIGITS", "-D",
30               "Set the number of digits in the numbering scheme.") do |d|
31         opts.num_digits = d.to_i
32       end
33       myparser.on("--dry-run", "-d",
34               "Show what would be done, without doing it.") do |d|
35         $fu_args = { :verbose => true, :noop => true }
36         opts.dry_run = true
37       end
38       myparser.on("--file-extension EXTENSION", "-e",
39               "The file extension for the files to rename.") do |e|
40         opts.extension = e
41       end
42       myparser.on("--preserve-names", "-p",
43               "Preserve the names while changing the numbers.") do |e|
44         opts.preserve_names = true
45       end
46     end
47
48     parser.parse!(args)
49     raise "invalid num_digits: #{opts.num_digits}" unless
50       opts.num_digits > 0
51     raise "must give an extension" unless opts.extension != nil
52     return opts
53   end
54 end
55
56 def pow(x, y)
57   ret = 1
58   (0...y).each do |z|
59     ret = ret * x
60   end
61   return ret
62 end
63 #.#{$opts.extension}").sort.each do |f|
64 def file_iter
65   Dir.glob("*.#{$opts.extension}").sort.each do |f| 
66     yield f
67   end
68 end
69
70 def count_files(file)
71   $total_files = $total_files + 1
72 end
73
74 def get_file_name(num)
75   return sprintf("%0#{$opts.num_digits}d", num)
76 end
77
78 def rename_files(file)
79   FileUtils.mv(file, "#{get_file_name(1 + $total_files)}.#{$opts.extension}",
80                $fu_args)
81   $total_files = $total_files + 1
82 end
83
84 def rename_files_keep_names(file)
85   proper_file = ""
86   if (file =~ /^[0-9. -]*(.*)$/) then
87     proper_file = $1
88   else
89     raise "can't find proper name for #{file}"
90   end
91   full_name = "#{get_file_name(1 + $total_files)} - #{proper_file}"
92   FileUtils.mv(file, full_name, $fu_args)
93   $total_files = $total_files + 1
94 end
95
96 # MAIN
97 begin
98   $opts = MyOptions.parse(ARGV)
99 rescue Exception => msg
100   $stderr.print("#{msg}.\nType --help to see usage information.\n")
101   exit 1
102 end
103
104 # make sure there aren't too many files
105 $total_files = 0
106 max_total_files = pow(10, $opts.num_digits) - 1
107 file_iter { |f| count_files(f) }
108 if ($total_files > max_total_files) then
109   raise "With #{$opts.num_digits} digit(s), we can only have at most \
110 #{max_total_files} files-- but there are #{$total_files} files in the \
111 #directory. Try setting a higher value for num_digits, using -D."
112 end
113
114 # rename files
115 $total_files = 0
116 if ( $opts.preserve_names ) then
117   file_iter { |f| rename_files_keep_names(f) }
118 else
119   file_iter { |f| rename_files(f) }
120 end
121
122 exit 0