filesortd 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ example.rb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format Fuubar
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in filesortd.gemspec
4
+ gemspec
5
+
6
+ gem 'rb-kqueue', '~> 0.2' if RbConfig::CONFIG['target_os'] =~ /freebsd/i
7
+ gem 'rb-fsevent', '~> 0.9.1' if RbConfig::CONFIG['target_os'] =~ /darwin(1.+)?$/i
8
+ gem 'rb-inotify', '~> 0.8.8', :github => 'mbj/rb-inotify' if RbConfig::CONFIG['target_os'] =~ /linux/i
9
+ gem 'wdm', '~> 0.0.3' if RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
10
+
11
+ if RbConfig::CONFIG['target_os'] =~ /darwin(1.+)?$/i
12
+ gem 'osx-plist'
13
+ end
14
+
15
+ group :development, :test do
16
+ gem 'rspec'
17
+ gem 'fuubar'
18
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 myfreeweb
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # Filesortd
2
+
3
+ A Ruby DSL for automatically sorting your files based on rules.
4
+ Like [Hazel](http://www.noodlesoft.com/hazel.php), but cross-platform, no GUI required.
5
+
6
+ ## Installation
7
+
8
+ $ gem install filesortd
9
+
10
+ If you're on OS X, also install osx-plist for things like `downloaded_from` (i.e. xattr support) to work:
11
+
12
+ $ gem install osx-plist
13
+
14
+ ## Usage
15
+
16
+ $ filesortd start yourconfig.rb
17
+
18
+ yourconfig.rb:
19
+
20
+ ```ruby
21
+ # DSL usage example
22
+
23
+ folder "/Users/myfreeweb/Downloads" do
24
+
25
+ # Do things to files that match a glob or a regex
26
+ match "*.mp3" do
27
+ mv "/Users/myfreeweb/Music"
28
+
29
+ # Do things if running on a particular OS
30
+ os :osx do
31
+ label :orange
32
+ end
33
+ end
34
+
35
+ # Mac OS X saves the location you downloaded a file from
36
+ downloaded_from %r{destroyallsoftware} do
37
+ mv "/Users/myfreeweb/Movies/DAS"
38
+ end
39
+ end
40
+
41
+
42
+ # You can watch multiple folders at once
43
+
44
+ folders "/Users/myfreeweb/Pictures", "/opt/pictures" do
45
+
46
+ # Do things to any files
47
+ any do
48
+ label :blue
49
+ end
50
+
51
+ match "*.png" do
52
+ pass "optipng"
53
+ label :green
54
+ end
55
+ end
56
+ ```
57
+
58
+ Actions:
59
+
60
+ - `contents` (or `read`) -- get the contents
61
+ - `rm` (or `remove`, `delete`, `unlink`) -- remove
62
+ - `cp` (or `copy`) -- copy
63
+ - `mv` (or `move`) -- move/rename
64
+ - `pipe(cmd)` -- start the command, pass the file to stdin, get the stdout
65
+ - `pass(cmd)` -- start the command, pass the path to the file as an argument, get the stdout
66
+ - `label(color)` -- set the OS X Finder label (:none, :orange, :red, :yellow, :blue, :purple, :green, :gray or :grey)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/filesortd ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require "filesortd"
3
+ require "filesortd/cli"
4
+
5
+ Filesortd::CLI.start
data/filesortd.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'filesortd/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "filesortd"
8
+ gem.version = Filesortd::VERSION
9
+ gem.authors = ["myfreeweb"]
10
+ gem.email = ["floatboth@me.com"]
11
+ gem.description = %q{Automatic rule-based sorting for your files. Like Hazel, but doesn't need a GUI.}
12
+ gem.summary = %q{Rule-based file sorting}
13
+ gem.homepage = "https://github.com/myfreeweb/filesortd"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "docile"
21
+ gem.add_dependency "listen"
22
+ gem.add_dependency "popen4"
23
+ gem.add_dependency "thor"
24
+ end
@@ -0,0 +1,75 @@
1
+ require "popen4"
2
+ require "fileutils"
3
+
4
+ module Filesortd
5
+ class Afile
6
+ attr_reader :path
7
+
8
+ def initialize(path)
9
+ @path = path
10
+ end
11
+
12
+ def contents
13
+ File.read @path
14
+ end
15
+ alias :read :contents
16
+
17
+ def rm
18
+ File.unlink @path
19
+ @path = nil
20
+ end
21
+ alias :remove :rm
22
+ alias :delete :rm
23
+ alias :unlink :rm
24
+
25
+ def cp(target)
26
+ FileUtils.cp @path, target
27
+ @path = target
28
+ end
29
+ alias :copy :cp
30
+
31
+ def mv(target)
32
+ FileUtils.mv @path, target
33
+ @path = target
34
+ end
35
+ alias :move :mv
36
+
37
+ def pipe(cmd)
38
+ out = nil
39
+ POpen4::popen4(cmd) do |stdout, stderr, stdin, pid|
40
+ stdin.puts File.read(@path)
41
+ stdin.close
42
+ out = stdout.read.strip
43
+ end
44
+ out
45
+ end
46
+
47
+ def pass(cmd)
48
+ out = nil
49
+ POpen4::popen4("#{cmd} #{@path.shellescape}") do |stdout, stderr, stdin, pid|
50
+ stdin.close
51
+ out = stdout.read.strip
52
+ end
53
+ out
54
+ end
55
+
56
+ def label(lbl)
57
+ if lbl.is_a? Symbol
58
+ idx = {
59
+ :none => 0,
60
+ :orange => 1,
61
+ :red => 2,
62
+ :yellow => 3,
63
+ :blue => 4,
64
+ :purple => 5,
65
+ :green => 6,
66
+ :gray => 7,
67
+ :grey => 7
68
+ }[lbl]
69
+ else
70
+ idx = lbl
71
+ end
72
+ system %{osascript -e 'tell app "Finder" to set label index of (POSIX file "#{@path}" as alias) to #{idx}' 2&>/dev/null}
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,38 @@
1
+ require "filesortd/matcher"
2
+ require "filesortd/afile"
3
+ require "docile"
4
+
5
+ module Filesortd
6
+ class Callback
7
+ attr_accessor :matchers
8
+
9
+ def initialize
10
+ @matchers = {}
11
+ end
12
+
13
+ def any(&callback)
14
+ @matchers[AlwaysTrueMatcher.new] = callback
15
+ end
16
+
17
+ def match(pattern, &callback)
18
+ @matchers[BasenameMatcher.new(pattern)] = callback
19
+ end
20
+
21
+ def downloaded_from(pattern, &callback)
22
+ pm = Matcher.new(pattern)
23
+ m = XattrMatcher.new("com.apple.metadata:kMDItemWhereFroms") do |elements, path|
24
+ elements.map { |el| pm.match(el) }.count(true) >= 1
25
+ end
26
+ @matchers[m] = callback
27
+ end
28
+
29
+ def call(paths)
30
+ paths.each do |path|
31
+ @matchers.each do |matcher, callback|
32
+ Docile.dsl_eval(Afile.new(path), &callback) if matcher.match(path)
33
+ end
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ require "thor"
2
+ require "filesortd"
3
+
4
+ module Filesortd
5
+ class Script
6
+ include Filesortd
7
+ attr_accessor :listeners
8
+ def initialize
9
+ @listeners = []
10
+ end
11
+ end
12
+
13
+ class CLI < Thor
14
+ default_task :start
15
+
16
+ desc 'start FILENAME', 'Start filesortd'
17
+ def start(filename)
18
+ puts 'Started filesortd'
19
+ begin
20
+ scpt = Script.new
21
+ scpt.instance_eval File.read(filename)
22
+ loop { sleep 0.1 }
23
+ # sleep to prevent 100% cpu load
24
+ rescue Interrupt
25
+ scpt.listeners.each do |l|
26
+ l.stop
27
+ end
28
+ puts 'Stopped filesortd'
29
+ end
30
+ end
31
+
32
+ desc 'version', 'Show the Guard version'
33
+ map %w(-v --version) => :version
34
+ def version
35
+ puts ::Filesortd::VERSION
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,19 @@
1
+ module Filesortd
2
+ def os(s, &block)
3
+ if s == current_os
4
+ block.call
5
+ end
6
+ end
7
+
8
+ private
9
+ def current_os
10
+ case RbConfig::CONFIG['target_os']
11
+ when /freebsd/i then :freebsd
12
+ when /darwin(1.+)?$/i then :osx
13
+ when /linux/i then :linux
14
+ when /mswin|mingw/i then :windows
15
+ else
16
+ :unknown
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ require "listen"
2
+ require "docile"
3
+ require "filesortd/callback"
4
+
5
+ module Filesortd
6
+ def folders(*paths, &block)
7
+ paths.select! do |path|
8
+ e = File.exists? path
9
+ puts "Folder does not exist: #{path}" unless e
10
+ e
11
+ end
12
+ callback = Docile.dsl_eval(Callback.new, &block)
13
+ cb = Proc.new do |modified, added, removed|
14
+ puts "Processing files: #{added}"
15
+ callback.call added
16
+ end
17
+ l = Listen.to(*paths).latency(0.5).change(&cb)
18
+ l.start(false)
19
+ @listeners << l
20
+ end
21
+ alias :folder :folders
22
+ end
@@ -0,0 +1,40 @@
1
+ module Filesortd
2
+ class Matcher < Struct.new(:pattern)
3
+ def match(s)
4
+ if pattern.is_a? Regexp
5
+ !pattern.match(s).nil? # return a boolean through "not nil"
6
+ elsif pattern.is_a? String
7
+ File.fnmatch(pattern, s)
8
+ end
9
+ end
10
+ end
11
+
12
+ class BasenameMatcher < Matcher
13
+ alias :super_match :match
14
+ def match(path)
15
+ super_match(File.basename(path))
16
+ end
17
+ end
18
+
19
+ class XattrMatcher
20
+ def initialize(xattr, &matcher)
21
+ require "osx/plist"
22
+ require "Shellwords"
23
+ @xattr = xattr
24
+ @matcher = matcher
25
+ end
26
+
27
+ def match(path)
28
+ return false unless `xattr -l #{path.shellescape}`.include? @xattr
29
+ str = [`xattr -px #{@xattr.shellescape} #{path.shellescape}`.gsub("\n", "").gsub(" ", "")].pack("H*")
30
+ pl = OSX::PropertyList.load(str)
31
+ @matcher.call(pl, path)
32
+ end
33
+ end
34
+
35
+ class AlwaysTrueMatcher
36
+ def match(s)
37
+ true
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module Filesortd
2
+ VERSION = "0.1.0"
3
+ end
data/lib/filesortd.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "filesortd/version"
2
+ require "filesortd/folder"
3
+ require "filesortd/callback"
4
+ require "filesortd/matcher"
5
+ require "filesortd/cond"
6
+
7
+ module Filesortd
8
+ end
@@ -0,0 +1,64 @@
1
+ require "filesortd/afile"
2
+ include Filesortd
3
+
4
+ describe Afile do
5
+ let(:path) { "/tmp/filesortdtest" }
6
+
7
+ it "shows contents" do
8
+ File.write path, "1"
9
+ Afile.new(path).contents.should == "1"
10
+ File.unlink path
11
+ end
12
+
13
+ it "copies" do
14
+ path2 = "/tmp/filesortdtest2"
15
+ File.write path, "1"
16
+ af = Afile.new(path)
17
+ af.cp path2
18
+ af.path.should == path2
19
+ File.exists?(path).should be_true
20
+ File.exists?(path2).should be_true
21
+ File.unlink path
22
+ File.unlink path2
23
+ end
24
+
25
+ it "moves" do
26
+ path2 = "/tmp/filesortdtest2"
27
+ File.write path, "1"
28
+ af = Afile.new(path)
29
+ af.mv path2
30
+ af.path.should == path2
31
+ File.exists?(path).should be_false
32
+ File.exists?(path2).should be_true
33
+ File.unlink path2
34
+ end
35
+
36
+ it "removes" do
37
+ File.write path, "1"
38
+ af = Afile.new(path)
39
+ af.rm
40
+ af.path.should be_nil
41
+ File.exists?(path).should be_false
42
+ end
43
+
44
+ it "pipes" do
45
+ File.write path, "1+2"
46
+ Afile.new(path).pipe("bc").should == "3"
47
+ File.unlink path
48
+ end
49
+
50
+ it "passes" do
51
+ File.write path, "123"
52
+ Afile.new(path).pass("cat").should == "123"
53
+ File.unlink path
54
+ end
55
+
56
+ it "labels" do
57
+ if RbConfig::CONFIG['target_os'] =~ /darwin(1.+)?$/i
58
+ File.write path, "123"
59
+ Afile.new(path).label(:red)
60
+ `osascript -e 'tell app "Finder" to get label index of (POSIX file "#{path}" as alias)'`.should == "2\n"
61
+ File.unlink path
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,17 @@
1
+ require "filesortd/callback"
2
+ include Filesortd
3
+
4
+ describe Callback do
5
+ let(:cb) { Callback.new }
6
+
7
+ it "executes callbacks for matched paths" do
8
+ true_matcher = double("matcher", :match => true)
9
+ false_matcher = double("matcher", :match => false)
10
+ true_called = false_called = false
11
+ cb.matchers[ true_matcher] = Proc.new { true_called = true }
12
+ cb.matchers[false_matcher] = Proc.new { false_called = true }
13
+ cb.call([""])
14
+ true_called.should be_true
15
+ false_called.should be_false
16
+ end
17
+ end
data/spec/cond_spec.rb ADDED
@@ -0,0 +1,28 @@
1
+ require "filesortd/cond"
2
+ include Filesortd
3
+
4
+ describe "os" do
5
+ it "executes on freebsd" do
6
+ RbConfig::CONFIG['target_os'] = 'freebsd'
7
+ os(:freebsd) { true }.should be_true
8
+ os(:linux) { true }.should be_nil
9
+ end
10
+
11
+ it "executes on osx" do
12
+ RbConfig::CONFIG['target_os'] = 'darwin11.3.0'
13
+ os(:osx) { true }.should be_true
14
+ os(:linux) { true }.should be_nil
15
+ end
16
+
17
+ it "executes on linux" do
18
+ RbConfig::CONFIG['target_os'] = 'linux'
19
+ os(:linux) { true }.should be_true
20
+ os(:osx) { true }.should be_nil
21
+ end
22
+
23
+ it "executes on windows" do
24
+ RbConfig::CONFIG['target_os'] = 'mingw'
25
+ os(:windows) { true }.should be_true
26
+ os(:osx) { true }.should be_nil
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ require "filesortd/matcher"
2
+ include Filesortd
3
+
4
+ describe BasenameMatcher do
5
+ it "matches regexps on filenames" do
6
+ BasenameMatcher.new(%r{hello-[0-9]+.mp3}).match("/Some/Folder/hello-123.mp3").should be_true
7
+ BasenameMatcher.new(%r{hello-[0-9]+.mp3}).match("/Some/Folder/321-goodbye.mp3").should be_false
8
+ end
9
+
10
+ it "matches globs on filenames" do
11
+ BasenameMatcher.new("*.jpg").match("/Some/Folder/pic.jpg").should be_true
12
+ BasenameMatcher.new("*.jpg").match("/Some/Folder/pic.png").should be_false
13
+ end
14
+ end
15
+
16
+ describe XattrMatcher do
17
+ let(:path) { "/tmp/xattrtest" }
18
+ let(:prop) { "com.apple.metadata:kMDItemWhereFroms" }
19
+ let(:downloaded_das) { "62 70 6C 69 73 74 30 30 A2 01 02 5F 10 B5 68 74\n74 70 73 3A 2F 2F 73 33 2E 61 6D 61 7A 6F 6E 61\n77 73 2E 63 6F 6D 2F 64 65 73 74 72 6F 79 61 6C\n6C 73 6F 66 74 77 61 72 65 2F 64 61 73 2D 30 30\n31 34 2D 65 78 74 72 61 63 74 69 6E 67 2D 6F 62\n6A 65 63 74 73 2D 69 6E 2D 64 6A 61 6E 67 6F 2E\n6D 6F 76 3F 41 57 53 41 63 63 65 73 73 4B 65 79\n49 64 3D 41 4B 49 41 49 4B 52 56 43 45 43 58 42\n43 34 5A 47 48 49 51 26 45 78 70 69 72 65 73 3D\n31 33 35 35 33 32 35 35 31 33 26 53 69 67 6E 61\n74 75 72 65 3D 64 6C 4D 48 52 6D 73 78 64 56 70\n45 6F 4B 58 44 62 50 38 59 6F 65 36 51 37 44 77\n25 33 44 5F 10 36 68 74 74 70 73 3A 2F 2F 77 77\n77 2E 64 65 73 74 72 6F 79 61 6C 6C 73 6F 66 74\n77 61 72 65 2E 63 6F 6D 2F 73 63 72 65 65 6E 63\n61 73 74 73 2F 63 61 74 61 6C 6F 67 08 0B C3 00\n00 00 00 00 00 01 01 00 00 00 00 00 00 00 03 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 FC" }
20
+
21
+ before { File.write path, "123" }
22
+ after { File.unlink path }
23
+
24
+ it "returns true for matched xattrs" do
25
+ system "xattr -wx #{prop.shellescape} '#{downloaded_das}' #{path.shellescape}"
26
+ m = XattrMatcher.new(prop) do |elements, path|
27
+ elements.map { |el| !(el =~ %r{destroyallsoftware}).nil? }.count(true) >= 1
28
+ end
29
+ m.match(path).should be_true
30
+ end
31
+
32
+ it "returns false for invalid xattrs" do
33
+ system "xattr -wx #{prop.shellescape} '#{downloaded_das}' #{path.shellescape}"
34
+ m = XattrMatcher.new(prop) do |elements, path|
35
+ elements.map { |el| !(el =~ %r{destroyNOsoftware}).nil? }.count(true) >= 1
36
+ end
37
+ m.match(path).should be_false
38
+ end
39
+
40
+ it "returns false for no xattrs" do
41
+ m = XattrMatcher.new(prop) do |elements, path|
42
+ elements.map { |el| !(el =~ %r{destroyallsoftware}).nil? }.count(true) >= 1
43
+ end
44
+ m.match(path).should be_false
45
+ end
46
+
47
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: filesortd
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - myfreeweb
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: docile
16
+ requirement: &70354624421460 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70354624421460
25
+ - !ruby/object:Gem::Dependency
26
+ name: listen
27
+ requirement: &70354624420780 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70354624420780
36
+ - !ruby/object:Gem::Dependency
37
+ name: popen4
38
+ requirement: &70354624420200 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70354624420200
47
+ - !ruby/object:Gem::Dependency
48
+ name: thor
49
+ requirement: &70354624419580 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70354624419580
58
+ description: Automatic rule-based sorting for your files. Like Hazel, but doesn't
59
+ need a GUI.
60
+ email:
61
+ - floatboth@me.com
62
+ executables:
63
+ - filesortd
64
+ extensions: []
65
+ extra_rdoc_files: []
66
+ files:
67
+ - .gitignore
68
+ - .rspec
69
+ - Gemfile
70
+ - LICENSE.txt
71
+ - README.md
72
+ - Rakefile
73
+ - bin/filesortd
74
+ - filesortd.gemspec
75
+ - lib/filesortd.rb
76
+ - lib/filesortd/afile.rb
77
+ - lib/filesortd/callback.rb
78
+ - lib/filesortd/cli.rb
79
+ - lib/filesortd/cond.rb
80
+ - lib/filesortd/folder.rb
81
+ - lib/filesortd/matcher.rb
82
+ - lib/filesortd/version.rb
83
+ - spec/afile_spec.rb
84
+ - spec/callback_spec.rb
85
+ - spec/cond_spec.rb
86
+ - spec/matcher_spec.rb
87
+ homepage: https://github.com/myfreeweb/filesortd
88
+ licenses: []
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 1.8.11
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Rule-based file sorting
111
+ test_files:
112
+ - spec/afile_spec.rb
113
+ - spec/callback_spec.rb
114
+ - spec/cond_spec.rb
115
+ - spec/matcher_spec.rb