class Fned::FilenameEdit
Public Class Methods
main(*args)
click to toggle source
# File lib/fned/filename_edit.rb, line 25 def self.main(*args) # Filenames may be in any encoding, i.e. have an invalid encoding if # the default encoding is not binary. Therefore ensure that every # argument is in binary encoding. args = args.map { |str| str.dup.force_encoding "binary" } options = {} option_parser = OptionParser.new do |parser| parser.version = VERSION parser.banner = "Usage: #{File.basename($0)} [options] <files..>" parser.on("-v", "--verbose", "verbose output") do |v| options[:verbose] = true end parser.on("-r", "--recursive", "rename files in all subdirectories") do |v| options[:recursive] = true end parser.on("-sSEPARATOR", "--separator=SEPARATOR", "separator between line number and filename") do |v| options[:separator] = v end end begin option_parser.parse!(args) rescue OptionParser::ParseError warn $!.message return false end if args.empty? $stderr.puts option_parser.help return false end self.new(args, options).run end
new(paths, options = {})
click to toggle source
# File lib/fned/filename_edit.rb, line 66 def initialize(paths, options = {}) @paths = paths.map { |path| Pathname.new(path) } @options = { :verbose => false, :recursive => false, }.merge(options) if @options[:recursive] @paths = @paths.map { |path| [path] + walk(path) }.flatten end # Ensure all paths are in binary encoding, otherwise comparison # wont work after reading the files back from the file. @paths.map! { |path| Pathname.new(path.to_s.force_encoding("binary")) } # Don't display the same path multiple times. @paths.uniq! # It is not possible to rename `.' and `..'. @paths.reject! { |path| %w(. ..).include?(path.basename.to_s) } @errors = [] end
Public Instance Methods
edit()
click to toggle source
# File lib/fned/filename_edit.rb, line 123 def edit # TODO: option to edit the full path or relative path instead of # basename only # TODO: hide filename extension items = @paths.map(&:basename).map(&:to_s) # add path before each block of files in the same directory comments = [] dir = nil @paths.each.with_index do |path, index| next if path.dirname == dir comments[index] = "#{path.dirname}/" dir = path.dirname end items_new = EditList.new(@options).edit(items, comments) items_new.map.with_index do |path, index| # TODO: Pathname#dirname + path breaks if path contains .. # because .. is resolved by removing one component which may # change the directory if symlinks are in the path. @paths[index].dirname + path if path end end
run()
click to toggle source
# File lib/fned/filename_edit.rb, line 148 def run rename = Rename.new(@options) @paths.zip(edit).each do |source, destination| # TODO: option to delete files (interatively?) that are dropped # from the list next unless destination rename.add(source, destination) end rename.rename_files.empty? end
walk(path)
click to toggle source
Recursively walk through path and return path of all entries. Does not include path itself.
# File lib/fned/filename_edit.rb, line 90 def walk(path) # TODO: descend into symlinked directories? # TODO: handle errors (ENOENT, ENOTDIR, ELOOP, EACCESS) return [path] unless path.lstat.directory? entries = path.entries .map do |entry| entry.to_s.force_encoding "binary" end .reject do |entry| %w(. ..).include?(entry) end .map do |entry| if (path + entry).lstat.directory? path + "#{entry}/" else path + entry end end .sort_by do |entry| [entry.lstat.directory? ? 0 : 1, entry.basename] end result = [] result += entries result += entries.map do |entry| if entry.lstat.directory? walk(entry) end end.compact.flatten result end