clean 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'clean'
5
+
6
+ include Options
7
+ include Config
8
+ include Destinations
9
+ include CommandUtil
10
+
11
+ $OPTS=get_options(ARGV.dup)
12
+
13
+ ##################################################
14
+ ### Make and run commands ########################
15
+ ##################################################
16
+
17
+ $OPTS[:dirs].each do |dir|
18
+ cmds=dir_commands(dir)
19
+ cmds+=file_commands(dir)
20
+
21
+ cmds.sort.map &:run
22
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'yaml'
3
+ require 'activesupport'
4
+ require 'fileutils'
5
+ require 'trollop'
6
+
7
+ Dir[File.join(File.dirname(__FILE__),'*.rb')].each do |file|
8
+ require file
9
+ end
@@ -0,0 +1,46 @@
1
+ ##################################################
2
+ ### Make commands ################################
3
+ ##################################################
4
+
5
+ module CommandUtil
6
+ def make_file_command filename
7
+ dest=destination_for filename
8
+
9
+ return nil unless dest
10
+
11
+ if dest=="_rm"
12
+ RemoveCommand.new filename
13
+ else
14
+ MoveCommand.new filename, dest
15
+ end
16
+ end
17
+
18
+ def file_commands dir
19
+ dir=File.expand_path dir
20
+ cmds=Dir[File.join(dir, '*')].map do |filename|
21
+ nil if File.directory? filename
22
+ make_file_command(File.basename(filename))
23
+ end
24
+
25
+ cmds.compact.map { |c| c.path=dir ; c }
26
+ end
27
+
28
+ def dir_commands dir
29
+ dir=File.expand_path dir
30
+
31
+ cmds=config['directories'].keys.map do |dest|
32
+ next if dest=='_rm'
33
+ path=File.join(dir,dest)
34
+ if File.exists?(path)
35
+ if !File.directory?(path)
36
+ Trollop::die "#{path} already exists, and isn't a directory"
37
+ else
38
+ nil
39
+ end
40
+ else
41
+ CreateCommand.new dest,dir
42
+ end
43
+ end
44
+ cmds.compact
45
+ end
46
+ end
@@ -0,0 +1,143 @@
1
+ class Command
2
+ attr_accessor :path
3
+
4
+ def priority ; nil ; end
5
+
6
+ def transform filename
7
+ if path
8
+ File.join path, filename
9
+ else
10
+ File.join '.', filename
11
+ end
12
+ end
13
+
14
+ def run
15
+ unless $OPTS[:silent]
16
+ dr=dry_run
17
+ puts(dry_run) if dry_run
18
+ end
19
+
20
+ real_run unless $OPTS[:dry_run]
21
+ end
22
+
23
+ def dry_run ; raise NotImplementedError ; end
24
+ def real_run ; raise NotImplementedError ; end
25
+
26
+ def <=> other
27
+ priority <=> other.priority
28
+ end
29
+ end
30
+
31
+ ##################################################
32
+ ### Move files ###################################
33
+ ##################################################
34
+
35
+ class MoveCommand < Command
36
+ def priority ; 2 ; end
37
+
38
+ def initialize *args
39
+ (@filename, @directory, @path)=args
40
+ end
41
+
42
+ def filename ; transform @filename ; end
43
+ def directory ; transform @directory ; end
44
+
45
+ def dry_run
46
+ case $OPTS[:on_collision]
47
+ when 'overwrite'
48
+ "mv #{filename} #{directory}"
49
+ when 'rename'
50
+ "mv #{filename} #{File.join(directory,unique_name)}"
51
+ else # 'ignore' also
52
+ # emit nothing
53
+ end
54
+ end
55
+
56
+ def real_run
57
+ case $OPTS[:on_collision]
58
+ when 'overwrite'
59
+ mv
60
+ when 'rename'
61
+ if collision?
62
+ FileUtils.mv filename, File.join(directory,unique_name)
63
+ else
64
+ mv
65
+ end
66
+ else # captures the 'ignore' option too
67
+ # do nothing
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def mv
74
+ FileUtils.mv filename, directory
75
+ end
76
+
77
+ def collision? fname=filename
78
+ File.exists?(File.join(directory,File.basename(fname)))
79
+ end
80
+
81
+ def unique_name
82
+ fname=filename
83
+
84
+ # make sure there's a real collision
85
+ return fname unless collision? fname
86
+
87
+ # ext is like ".jpg"
88
+ ext=File.extname(fname)
89
+
90
+ # Base is the filename - dir and extension, so /foo/bar.txt -> bar
91
+ base=File.basename(fname,ext)
92
+
93
+ # loop until we find an n that'll work. Start with bar-1.txt
94
+ n=1
95
+ n+=1 while collision?("#{base}-#{n}#{ext}")
96
+
97
+ "#{base}-#{n}#{ext}"
98
+ end
99
+ end
100
+
101
+ ##################################################
102
+ ### Create directories ###########################
103
+ ##################################################
104
+
105
+ class CreateCommand < Command
106
+ def priority ; 1 ; end
107
+
108
+ def initialize *args
109
+ (@dirname, @path)=args
110
+ end
111
+
112
+ def dirname ; transform @dirname ; end
113
+
114
+ def dry_run
115
+ "mkdir #{dirname}"
116
+ end
117
+
118
+ def real_run
119
+ FileUtils.mkdir_p dirname
120
+ end
121
+ end
122
+
123
+ ##################################################
124
+ ### Remove files #################################
125
+ ##################################################
126
+
127
+ class RemoveCommand < Command
128
+ def priority ; 3 ; end
129
+
130
+ def initialize *args
131
+ (@filename, @path)=args
132
+ end
133
+
134
+ def filename ; transform @filename ; end
135
+
136
+ def dry_run
137
+ "rm #{filename}"
138
+ end
139
+
140
+ def real_run
141
+ FileUtils.rm filename
142
+ end
143
+ end
@@ -0,0 +1,31 @@
1
+ ##################################################
2
+ ### Read config file #############################
3
+ ##################################################
4
+
5
+ module Config
6
+ def config
7
+ return @config if @config
8
+
9
+ file=File.expand_path($OPTS[:config_file])
10
+ if File.exists? file
11
+ @config||=YAML.load(File.open(file))
12
+ else
13
+ ex=File.expand_path(File.join(File.dirname(__FILE__),
14
+ '..','res','clean.yml'))
15
+ puts "Warning: config file #{file} not found; using default #{ex}"
16
+ @config||=YAML.load(File.open(ex))
17
+ end
18
+ end
19
+
20
+ def destination_map
21
+ unless @destination_map
22
+ @destination_map={}
23
+ config['directories'].each do |directory, extensions|
24
+ extensions.each do |ext|
25
+ @destination_map[ext]=directory
26
+ end
27
+ end
28
+ end
29
+ @destination_map
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ ##################################################
2
+ ### Find move destinations #######################
3
+ ##################################################
4
+
5
+ module Destinations
6
+ def all_extensions_for filename
7
+ destination_map.keys.map{ |extension|
8
+ safe_extension=Regexp.escape(extension)
9
+ (filename =~ Regexp.new("#{safe_extension}$")) ? extension : nil
10
+ }.compact
11
+ end
12
+
13
+ def destination_for filename
14
+ longest_extension=
15
+ all_extensions_for(filename).sort{|a,b|
16
+ -(a<=>b)
17
+ }[0]
18
+
19
+ destination_map[longest_extension]
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ ##################################################
2
+ ### Options ######################################
3
+ ##################################################
4
+
5
+ module Options
6
+ def get_options args=ARGV
7
+ opts=Trollop::options(args) do
8
+ version "cleaner 1.1.1"
9
+ banner <<-EOS
10
+ Cleaner is a program for automatically sorting files based on their extensions.
11
+
12
+ Usage:
13
+ clean [options] <dirs>+
14
+
15
+ where [options] are:
16
+ EOS
17
+ opt(:dry_run, "Just print commands, don't move anything",
18
+ :default=>false)
19
+ opt(:config_file, "Where to load mappings from",
20
+ :default=>'~/.clean.yml', :type=>String)
21
+ opt(:silent, "Don't print commands",
22
+ :default=>false)
23
+ opt(:on_collision, "If the destination file already exists, rename, overwrite, or ignore?",
24
+ :default=>'rename')
25
+ end
26
+
27
+ opts[:dirs]=( args.empty? ? ['.'] : args )
28
+
29
+ opts
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ directories:
2
+ images:
3
+ - .jpg
4
+ - .JPG
5
+ - .gif
6
+ - .GIF
7
+ - .png
8
+ - .jpeg
9
+
10
+ documents:
11
+ - .pdf
12
+ - .doc
13
+ - .ps
14
+
15
+ archives:
16
+ - .tar.gz
17
+ - .gz
18
+ - .zip
19
+ - .bzip
20
+
21
+ programs:
22
+ - .dmg
23
+ - .app
24
+ - .pkg
25
+
26
+ windows:
27
+ - .exe
28
+ - .EXE
29
+
30
+ code:
31
+ - .java
32
+ - .rb
33
+
34
+ _rm:
35
+ - .torrent
36
+ - "~"
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clean
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 1
8
+ - 1
9
+ version: 1.1.1
10
+ platform: ruby
11
+ authors:
12
+ - Andrews, Ross
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2009-03-08 00:00:00 -06:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activesupport
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 1
30
+ - 0
31
+ version: 2.1.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: trollop
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 1
43
+ - 10
44
+ - 2
45
+ version: 1.10.2
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ description:
49
+ email: randrews@geekfu.org
50
+ executables:
51
+ - clean
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - res/clean.yml
58
+ - lib/clean.rb
59
+ - lib/command_util.rb
60
+ - lib/commands.rb
61
+ - lib/config.rb
62
+ - lib/destinations.rb
63
+ - lib/options.rb
64
+ has_rdoc: true
65
+ homepage: http://geekfu.org
66
+ licenses: []
67
+
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.6
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: A utility for sorting messy folders
94
+ test_files: []
95
+