Ara.T.Howard wrote:
> On Mon, 5 Sep 2005, Vincent Foley wrote:
>
> > Hello guys,
> >
> > I wrote this little method to return the size of a given directory, but
> > I think it's very ugly.  Could anyone help me clean it up a bit?
> >
[snip]
>
> just thought i'd point out that every solution posted thus far fails in a
> variety of ways when links are considered - in the best cases linked files are
> counted twice or linked dirs are not checked, in the worst case infinite loops
> occur.  the methods using 'Dir[glob]' v.s. 'Find::find' suffer from the link
> issue but also will perfom badly on large file systems.  unfortunately ruby's
> built-in 'Find::find' cannot deal with links - for that you have to rely on
> motoyuki kasahara's Find2 module, which you can get off of the raa.  i have it
> inlined in my personal library (alib - also on the raa) with few small bug
> fixes and interface additions, to use you would do something like:
>
>    require 'alib'
>
>    def dir_size dir
>      size = 0
>      totalled = {}
>      ALib::Util::find2(dir, 'follow' => true) do |path, stat|
>        begin
>          next if totalled[stat.ino]
>          next unless stat.file?
>          size += stat.size
>        ensure
>          totalled[stat.ino] = true
>        end
>      end
>      size
>    end
>
>    p dir_size('.')
>
> this handles huge directories, duplicate files (links) in a directory, linked
> directories, and potential infinite loops.  i think this is about as simply as
> one can write this without introducing subtle, or not so subtle, bugs.

This solution fails under windoze by always returning 0, apparently
because
File.stat(path).ino always returns 0.

If you're stuck with windoze, use the previously posted

def Dir.size(name)
  Dir[File.join(name, "**/*")].select{|f|
File.file?(f)}.inject(0){|sum,f|
    sum + File.size(f)
  }
end