Sat 2008-12-13 ( En pr )

I wrote a simple version of the UNIX directory disk usage tool du (disk usage). Its output should be exactly the same as du -sh. Call it with the name of a file or folder.

Update: This is the second version, using a better method for the bytesize output and guessing the system’s blocksize.

def du_format size
  size = Kernel.Float size
  magnitude = (Math.log(size) / Math.log(1024)).floor
  unit = 'BKMGTPEZY'[magnitude, 1]
  size /= 1024.0 ** magnitude
  sizestr = '%3.1f' % size
  sizestr = size.round.to_s.rjust(3) if sizestr[/\d+.\d/] && $&.size > 3
  sizestr + unit
end
BLOCK_SIZE = File.stat($0).blksize rescue 1
def read_file path
  begin
    stat = File.stat path
  rescue SystemCallError
    return File.symlink?(path) ? BLOCK_SIZE : 0
  end
  if stat.file?
    stat.size + (-stat.size % BLOCK_SIZE)
  elsif stat.directory?
    read_dir path
  else
    0
  end
end
def read_dir path
  size = 0
  Dir.chdir path do
    for file in Dir.entries '.'
      next if file == '.' || file == '..'
      size += read_file file
    end
  end
  size
rescue SystemCallError
  0
end
path = ARGV.first || '.'
size = read_file path
puts "%s\t%s" % [du_format(size), path]

If you want to check how good it matched du output for you, try

find ~ -depth 1 -exec du -sh {} \; -exec ruby dirsize.rb {} \;

or something. It’s about half as fast as du on Mac OS X. I like the recursion :)

Say something! / Sag was!

No markup, just plain monospace text. / Kein Markup, nur Normschrift-Klartext.