Created
February 22, 2010 07:53
-
-
Save akm/310915 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env ruby | |
require 'fileutils' | |
require "optparse" | |
OPTIONS = { | |
:default => 'n', | |
:confirmation => :once, | |
:sort => :path, | |
:display_format => '"mtime size path"', | |
:verbose => false | |
} | |
OptionParser.new do |opt| | |
opt.on("-o", "--confirm-once"){ OPTIONS[:confirmation] = :once} | |
opt.on("-e", "--confirm-each"){ OPTIONS[:confirmation] = :each} | |
opt.on("-y", "--confirm-none"){ OPTIONS[:confirmation] = :none} | |
opt.on("-D", "--display-format=#{OPTIONS[:display_format]}"){|v| OPTIONS[:display_format] = v} | |
opt.on("-R", "--sort-reverse"){ OPTIONS[:sort_reverse] = true} | |
opt.on("-P", "--sort-by-path" ){ OPTIONS[:sort] = :path} | |
opt.on("-N", "--sort-by-name" ){ OPTIONS[:sort] = :name} | |
opt.on("-S", "--sort-by-size" ){ OPTIONS[:sort] = :size} | |
opt.on("-A", "--sort-by-last-accessed-time"){ OPTIONS[:sort] = :atime} | |
opt.on("-C", "--sort-by-last-changed-time" ){ OPTIONS[:sort] = :ctime} | |
opt.on("-M", "--sort-by-last-modified-time"){ OPTIONS[:sort] = :mtime} | |
opt.on("-d", "--default=no"){|v| OPTIONS[:default] = v} | |
opt.on("-n", "--noop"){ OPTIONS[:noop] = true} | |
opt.on("-v", "--verbose"){ OPTIONS[:verbose] = true} | |
opt.parse!(ARGV) | |
end | |
class MetaFile | |
attr_reader :path | |
def initialize(path) | |
@path = path | |
end | |
def name | |
File.basename(@path) | |
end | |
alias_method :display_path, :path | |
alias_method :display_name, :name | |
def size | |
File.size(@path) | |
end | |
def display_size | |
self.class.commify(size) | |
end | |
%w(atime ctime mtime).each do |attr| | |
self.module_eval(<<-"EOS") | |
def #{attr} | |
File.#{attr}(@path) | |
end | |
def display_#{attr} | |
#{attr}.strftime("%Y-%m-%d %H:%M:%S") | |
end | |
EOS | |
end | |
def display | |
"%s % 20s byte %s" % [display_mtime, display_size, display_path] | |
end | |
def rm | |
FileUtils.rm(@path, | |
:verbose => self.class.verbose, | |
:noop => self.class.noop) | |
end | |
class << self | |
attr_accessor :verbose | |
attr_accessor :noop | |
def commify(num) | |
num.to_s.reverse.scan(/\d{1,3}/).join(",").reverse | |
end | |
def glob(*paths) | |
targets = [] | |
paths.each do |path| | |
targets.concat(Dir.glob(path)) | |
end | |
targets.map{|path| MetaFile.new(path) } | |
end | |
end | |
end | |
MetaFile.verbose = !!OPTIONS[:verbose] | |
MetaFile.noop = !!OPTIONS[:noop] | |
targets = MetaFile.glob(ARGV) | |
sort_attr = OPTIONS[:sort] || :path | |
sorted = targets.sort_by{|target| target.send(sort_attr) } | |
sorted = sorted.reverse if OPTIONS[:sort_reverse] | |
def confirm(msg, prompt, help_msg) | |
choices = /^[#{prompt.downcase}]/i | |
help_msg << "\nh - help, show this help" | |
valid_answer = false | |
begin | |
print "#{msg} [#{prompt}] " | |
answer = STDIN.gets | |
answer = OPTIONS[:default] if answer.strip.empty? | |
case answer | |
when /^h/i then | |
puts help_msg | |
when choices then | |
valid_answer = true | |
yield(answer) | |
end | |
end until valid_answer | |
end | |
if OPTIONS[:confirmation] == :once | |
sorted.each do |target| | |
puts target.display | |
end | |
end | |
puts "total %d files %s byte" % [ | |
sorted.length, | |
MetaFile.commify(sorted.inject(0){|sum, t| sum + t.size})] | |
def delete_files(files) | |
files.each{|f| f.rm} | |
end | |
def confirm_once(files) | |
help_msg = <<EOS | |
y - yes | |
n - no | |
e - confirm each files | |
EOS | |
prompt = (OPTIONS[:default] =~ /^y/i) ? 'Yne' : 'yNe' | |
confirm("Now removing them. Are you sure?", prompt , help_msg) do |answer| | |
case answer | |
when /^y/i then delete_files(files) | |
when /^n/i then puts "aborted" | |
when /^e/i then confirm_each(files) | |
end | |
end | |
end | |
def confirm_each(files) | |
help_msg = <<EOS | |
y - yes, overwrite | |
n - no, do not overwrite | |
a - all, overwrite this and all others | |
q - quit, abort | |
EOS | |
prompt = (OPTIONS[:default] =~ /^y/i) ? 'Ynaq' : 'yNaq' | |
all_yes = false | |
files.each do |target| | |
if all_yes | |
target.rm | |
next | |
end | |
confirm("delete? #{target.display}", prompt, help_msg) do |answer| | |
case answer | |
when /^y/i then target.rm | |
when /^n/i then # do nothing | |
when /^a/i then target.rm; all_yes = true | |
when /^q/i then puts "aborted"; exit(true) | |
end | |
end | |
end | |
end | |
case OPTIONS[:confirmation] | |
when :none then delete_files(sorted) | |
when :once then confirm_once(sorted) | |
when :each then confirm_each(sorted) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment