durb 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ === 0.1 / 2009-02-11
2
+
3
+ * First release
4
+
@@ -0,0 +1,11 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/durb
6
+ lib/directory_inspector.rb
7
+ lib/directory_node.rb
8
+ lib/durb.rb
9
+ lib/human_readable.rb
10
+ lib/reducer.rb
11
+ lib/text_output.rb
@@ -0,0 +1,40 @@
1
+ = durb
2
+
3
+ * http://durb.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ durb is a smarter du. It's a CLI ruby utility which intelligently displays disk usage under a directory or filesystem. durb hides unimportant directories to make it easier to find out where all your disk-space has gone.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Slow
12
+
13
+ == SYNOPSIS:
14
+
15
+ durb [-s size] [directory]
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * None
20
+
21
+ == INSTALL:
22
+
23
+ * sudo gem install
24
+
25
+ == LICENSE:
26
+
27
+ Copyright (c) 2009 Matteo Sasso
28
+
29
+ This program is free software: you can redistribute it and/or modify
30
+ it under the terms of the GNU General Public License as published by
31
+ the Free Software Foundation, either version 3 of the License, or
32
+ (at your option) any later version.
33
+
34
+ This program is distributed in the hope that it will be useful,
35
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
36
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37
+ GNU General Public License for more details.
38
+
39
+ You should have received a copy of the GNU General Public License
40
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -0,0 +1,11 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/durb.rb'
6
+
7
+ Hoe.new('durb', Durb::VERSION) do |p|
8
+ p.developer('Matteo Sasso', 'matteo.sasso@gmail.com')
9
+ end
10
+
11
+ # vim: syntax=Ruby
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'getoptlong'
4
+
5
+ require 'human_readable'
6
+ require 'text_output'
7
+ require 'directory_node'
8
+ require 'directory_inspector'
9
+ require 'reducer'
10
+
11
+ include HumanReadable
12
+
13
+ DEFAULT_SIZE = "100m"
14
+
15
+ opts = GetoptLong.new(
16
+ ["--size", "-s", GetoptLong::REQUIRED_ARGUMENT],
17
+ ["--width", "-w", GetoptLong::REQUIRED_ARGUMENT],
18
+ ["--verbose", "-v", GetoptLong::NO_ARGUMENT],
19
+ ["--one-filesystem", "-x", GetoptLong::NO_ARGUMENT])
20
+
21
+ opts.each do |opt, arg|
22
+ case opt
23
+ when "--size"
24
+ $size = arg
25
+ when "--width"
26
+ $width = arg.to_i
27
+ when "--verbose"
28
+ $verbose = true
29
+ when "--one-filesystem"
30
+ $one_filesystem = true
31
+ end
32
+ end
33
+
34
+ $path = ARGV[0] ? File.expand_path(ARGV[0]) : File.expand_path(".")
35
+ $size = DEFAULT_SIZE if not $size or $size == 0
36
+
37
+ tree = DirectoryInspector.new($path, {:one_filesystem => $one_filesystem}).run
38
+ reduced_tree = Reducer.run(tree, text_to_size($size))
39
+ TextOutput.new(reduced_tree, $stdout, {:width => $width, :verbose => $verbose}).print_all(text_to_size($size))
@@ -0,0 +1,58 @@
1
+ class DirectoryInspector
2
+ def initialize(path, options = {})
3
+ @path = DirectoryNode.string_to_path(path)
4
+ @filesystem = options[:one_filesystem] ? File.stat(path).dev : nil
5
+ end
6
+
7
+ def run
8
+ make_node(@path)
9
+ end
10
+
11
+ protected
12
+ def make_node(path)
13
+ size, files, subdirectories = inspect(path)
14
+
15
+ dir = DirectoryNode.new(path, size, files)
16
+ subdirectories.map{|p| make_node(p)}.select{|n| not n.nil?}.each do |n|
17
+ dir.add_subdirectory(n)
18
+ end
19
+
20
+ return dir
21
+ end
22
+
23
+ def inspect(path)
24
+ path_string = DirectoryNode.path_to_string(path)
25
+ size = files = 0
26
+ subdirectories = []
27
+
28
+ begin
29
+ dir = Dir.new(path_string)
30
+ rescue Errno::EACCES
31
+ raise $!
32
+ rescue Errno::ENOENT
33
+ return nil
34
+ end
35
+ dir.each do |f|
36
+ next if [".", ".."].include?(f)
37
+ fname = path_string + f
38
+ begin
39
+ st = File.lstat(fname)
40
+ rescue Errno::EACCES
41
+ raise $!
42
+ rescue Errno::ENOENT, Errno::ELOOP
43
+ next
44
+ end
45
+ next if st.symlink?
46
+ next if @filesystem and st.dev != @filesystem
47
+ if st.file?
48
+ size += (512 * st.blocks)
49
+ files += 1
50
+ elsif st.directory?
51
+ # Need to add directory size?
52
+ subdirectories << path + [f]
53
+ end
54
+ end
55
+
56
+ return size, files, subdirectories
57
+ end
58
+ end
@@ -0,0 +1,41 @@
1
+ class DirectoryNode
2
+ attr_reader :path, :subdirectories
3
+ attr_accessor :size, :files, :subsize, :subfiles, :significant
4
+
5
+ def initialize(path, size, files, significant = true)
6
+ @path = path
7
+ @size = size
8
+ @files = files
9
+ @subsize = @subfiles = 0
10
+ @significant = significant
11
+ @subdirectories = []
12
+ end
13
+
14
+ def add_subdirectory(d)
15
+ @subdirectories << d
16
+ if d.significant
17
+ @subsize += d.size + d.subsize
18
+ @subfiles += d.files + d.subfiles
19
+ end
20
+ end
21
+
22
+ def significant_subdirectories
23
+ @subdirectories.select{|n| n.significant}
24
+ end
25
+
26
+ def insignificant_subdirectories
27
+ @subdirectories.select{|n| not n.significant}
28
+ end
29
+
30
+ def path_string
31
+ self.class.path_to_string(@path)
32
+ end
33
+
34
+ def self.path_to_string(path)
35
+ path.length == 0 ? '/' : ('/' + path.join('/') + '/')
36
+ end
37
+
38
+ def self.string_to_path(path_string)
39
+ path_string == '/' ? [] : path_string.split('/').reject{|component| component.empty?}
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ class Durb
2
+ VERSION = '0.1'
3
+ end
@@ -0,0 +1,27 @@
1
+ module HumanReadable
2
+ SUFFIXES = [' ', 'k', 'm', 'g', 't', 'p']
3
+
4
+ def text_to_size(text)
5
+ number, multiplier = text.match(/^(\d+)(\D)?$/)[1..-1]
6
+ exp = multiplier ? SUFFIXES.index(multiplier) : 0
7
+ raise ArgumentError, "Unknown suffix: %s" % multiplier if not exp
8
+
9
+ return number.to_i * 1024**exp
10
+ end
11
+
12
+ def size_to_text(size)
13
+ exp = 0
14
+ while size > 999
15
+ size /= 1024.0
16
+ exp += 1
17
+ end
18
+
19
+ if size >= 100 or exp == 0
20
+ "%d%s" % [size.round, SUFFIXES[exp]]
21
+ elsif size >= 10
22
+ "%.1f%s" % [size, SUFFIXES[exp]]
23
+ else
24
+ "%.2f%s" % [size, SUFFIXES[exp]]
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ module Reducer
2
+ def self.run(tree, threshold)
3
+ rtree = DirectoryNode.new(tree.path, tree.size, tree.files)
4
+
5
+ tree.subdirectories.each{|n| rtree.add_subdirectory(run(n, threshold))}
6
+ rtree.insignificant_subdirectories.each do |n|
7
+ rtree.size += n.size
8
+ rtree.files += n.files
9
+ end
10
+ rtree.significant = (rtree.size >= threshold or not rtree.significant_subdirectories.empty?)
11
+
12
+ return rtree
13
+ end
14
+ end
@@ -0,0 +1,76 @@
1
+ class TextOutput
2
+ def initialize(tree, output, options = {})
3
+ @width = calc_width(tree) + (options[:verbose] ? 23 : 11)
4
+ @output = output
5
+ if output.tty?
6
+ begin
7
+ tput = open("|tput cols")
8
+ max_width = tput.gets.to_i
9
+ rescue
10
+ max_width = 80
11
+ end
12
+ @width = [max_width, @width].min
13
+ end
14
+ @tree = tree
15
+ @options = options
16
+ end
17
+
18
+ def print_all(size)
19
+ if @options[:verbose]
20
+ heading = "SELF SUBS/# "
21
+ puts((" " * (@width - heading.size - 2)) + heading)
22
+ end
23
+ print_tree(@tree, size)
24
+ end
25
+
26
+ def print_tree(tree, size, indentation = 0)
27
+ print_node(tree, size, indentation)
28
+ tree.significant_subdirectories.each do |n|
29
+ print_tree(n, size, indentation + 2)
30
+ end
31
+ end
32
+
33
+ def print_node(node, size, indentation)
34
+ if $verbose
35
+ subsize_text = size_to_text(node.subsize)
36
+ if node.subsize == 0 and node.size == 0
37
+ size_text = nil; raise "can this happen?"
38
+ elsif node.subsize == 0
39
+ size_text = "%5s " % size_to_text(node.size)
40
+ elsif node.size == 0
41
+ size_text = " %5s/%-4d" % [size_to_text(node.subsize), node.subdirectories.size]
42
+ else
43
+ size_text = "%5s + %5s/%-4d" % [size_to_text(node.size), size_to_text(node.subsize), node.subdirectories.size]
44
+ end
45
+ else
46
+ total_size = node.size #+ node.subsize
47
+ size_text = total_size < size ? nil : size_to_text(total_size)
48
+ end
49
+ align((' ' * indentation) + node.path_string, size_text)
50
+ end
51
+
52
+ def calc_width(tree, indentation = 0)
53
+ (tree.significant_subdirectories.map{|n| calc_width(n, indentation + 2)} +
54
+ [tree.path_string.size + indentation]).max
55
+ end
56
+
57
+ def align(left, right)
58
+ right = "" if not right
59
+ size = @width - (left.size + right.size + 4)
60
+ if size <= 0
61
+ left = left[0..(size-4)] + '...'
62
+ size = 0
63
+ end
64
+ @output.print left, ' '
65
+ if not right.empty?
66
+ y = 0
67
+ while size > 0
68
+ @output.print(((y + left.size) % 2 == 0) ? '.' : ' ')
69
+ size -= 1
70
+ y += 1
71
+ end
72
+ @output.print ' ', right
73
+ end
74
+ @output.print "\n"
75
+ end
76
+ end
File without changes
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: durb
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Matteo Sasso
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-11 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.3
24
+ version:
25
+ description: durb is a smarter du. It's a CLI ruby utility which intelligently displays disk usage under a directory or filesystem. durb hides unimportant directories to make it easier to find out where all your disk-space has gone.
26
+ email:
27
+ - matteo.sasso@gmail.com
28
+ executables:
29
+ - durb
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - Manifest.txt
35
+ - README.txt
36
+ files:
37
+ - History.txt
38
+ - Manifest.txt
39
+ - README.txt
40
+ - Rakefile
41
+ - bin/durb
42
+ - lib/directory_inspector.rb
43
+ - lib/directory_node.rb
44
+ - lib/durb.rb
45
+ - lib/human_readable.rb
46
+ - lib/reducer.rb
47
+ - lib/text_output.rb
48
+ has_rdoc: true
49
+ homepage: http://durb.rubyforge.org
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --main
53
+ - README.txt
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project: durb
71
+ rubygems_version: 1.3.1
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: durb is a smarter du
75
+ test_files:
76
+ - test/test_durb.rb