Ruby equivalent for `du`

I wrote a simple method for recursively finding the size of a
directory, because I didn't see anything in File::Stat or FileUtils
that does that. Am I missing it? Does Ruby already have an
equivalent to `du`?

  def size(f)
    return File.size(f) unless File.directory?(f)
    Dir.entries(f)[2..-1].inject(0) {|total, s| total + size(File.join(f, s))}
  end

Couple problems with that approach 1.) assuming that ".", ".." are the
first elements of the entries array, 2.) for deep directories you'll
run out of stack very quickly. Have a look at the example at the top
of the Find module. :wink:

[1] http://www.ruby-doc.org/core/classes/Find.html

Regards,
Jordan

···

On Dec 5, 10:51 am, Christian von Kleist <cvonkle...@gmail.com> wrote:

I wrote a simple method for recursively finding the size of a
directory, because I didn't see anything in File::Stat or FileUtils
that does that. Am I missing it? Does Ruby already have an
equivalent to `du`?

  def size(f)
    return File.size(f) unless File.directory?(f)
    Dir.entries(f)[2..-1].inject(0) {|total, s| total + size(File.join(f, s))}
  end

Good point! Something like %w(. ..).include?(file) would be better
than relying on . and .. to be the first two entries. I'm not worried
about stack space, though I did consider it. For this application I
won't find thousands of levels of subdirectories, and even then I
probably wouldn't run out of stack space. I could rewrite the
recursion as a loop, but...

As you suggested, I should have used Find.find instead. The
implementation is simpler, more readable, and more robust:

require 'find'
def size(f)
  total = 0
  Find.find(f) {|s| total += File.directory?(s) ? 0 : File.size(s)}
  total
end

(For my application I don't care about the size of directories since
those are highly configuration dependent and this script must produce
the same result with the same file/directory tree on different
computers.)

Thanks, Jordan!

···

On Dec 5, 2007 12:10 PM, MonkeeSage <MonkeeSage@gmail.com> wrote:

On Dec 5, 10:51 am, Christian von Kleist <cvonkle...@gmail.com> wrote:
> I wrote a simple method for recursively finding the size of a
> directory, because I didn't see anything in File::Stat or FileUtils
> that does that. Am I missing it? Does Ruby already have an
> equivalent to `du`?
>
> def size(f)
> return File.size(f) unless File.directory?(f)
> Dir.entries(f)[2..-1].inject(0) {|total, s| total + size(File.join(f, s))}
> end

Couple problems with that approach 1.) assuming that ".", ".." are the
first elements of the entries array, 2.) for deep directories you'll
run out of stack very quickly. Have a look at the example at the top
of the Find module. :wink:

[1] http://www.ruby-doc.org/core/classes/Find.html

Regards,
Jordan

No problem. :slight_smile:

Regards,
Jordan

···

On Dec 5, 11:53 am, Christian von Kleist <cvonkle...@gmail.com> wrote:

On Dec 5, 2007 12:10 PM, MonkeeSage <MonkeeS...@gmail.com> wrote:

> On Dec 5, 10:51 am, Christian von Kleist <cvonkle...@gmail.com> wrote:
> > I wrote a simple method for recursively finding the size of a
> > directory, because I didn't see anything in File::Stat or FileUtils
> > that does that. Am I missing it? Does Ruby already have an
> > equivalent to `du`?

> > def size(f)
> > return File.size(f) unless File.directory?(f)
> > Dir.entries(f)[2..-1].inject(0) {|total, s| total + size(File.join(f, s))}
> > end

> Couple problems with that approach 1.) assuming that ".", ".." are the
> first elements of the entries array, 2.) for deep directories you'll
> run out of stack very quickly. Have a look at the example at the top
> of the Find module. :wink:

> [1]http://www.ruby-doc.org/core/classes/Find.html

> Regards,
> Jordan

Good point! Something like %w(. ..).include?(file) would be better
than relying on . and .. to be the first two entries. I'm not worried
about stack space, though I did consider it. For this application I
won't find thousands of levels of subdirectories, and even then I
probably wouldn't run out of stack space. I could rewrite the
recursion as a loop, but...

As you suggested, I should have used Find.find instead. The
implementation is simpler, more readable, and more robust:

require 'find'
def size(f)
  total = 0
  Find.find(f) {|s| total += File.directory?(s) ? 0 : File.size(s)}
  total
end

(For my application I don't care about the size of directories since
those are highly configuration dependent and this script must produce
the same result with the same file/directory tree on different
computers.)

Thanks, Jordan!