Is there a ruby way to get the disk size of a directory?

J

jazzez ravi

Juan said:
I was wondering if there was something to du -h?

Juan

Hi Zanos,


Code:

puts files = `cd`,`dir /s`

Output:

C:\raveendran\File_concept
Volume in drive C has no label.
Volume Serial Number is F40B-0762

Directory of C:\raveendran\File_concept

12/26/2008 05:14 PM <DIR> .
12/26/2008 05:14 PM <DIR> ..
05/12/2008 10:43 AM 211 filerite.rb
03/30/2009 09:37 AM 298 filesize.rb
12/22/2008 05:57 PM 239 file_last_line.rb
07/17/2008 12:12 PM 139 findfile.rb
08/08/2008 12:44 PM 225 folder.rb
5 File(s) 1,112 bytes

Total Files Listed:
5 File(s) 1,112 bytes
2 Dir(s) 9,278,435,328 bytes free


Let me know you expecting this or not ?

Regards,
P.Raveendran
http://raveendran.wordpress.com
 
J

John Carter

I was wondering if there was something to du -h?

Umm, it's pretty ugly what I do have... it invokes the Linux statfs
system call...

$ irb -r StatFs64.rb
irb(main):001:0> a = StatFs64.new( "/home")
=> #<StatFs64:0xb7cd8108 @statfs64={"f_spare0"=>0, "f_spare1"=>0, "f_files"=>5750784, "f_bfree"=>3332642, "f_bsize"=>4096, "f_spare2"=>0, "f_blocks"=>11299984, "f_spare3"=>0, "f_spare4"=>0, "f_ffree"=>4574344, "f_fsid0"=>1992275371, "f_fsid1"=>157862524, "f_frsize"=>4096, "f_namelen"=>255, "f_bavail"=>2758620, "f_type"=>61267}>
irb(main):002:0> p a.free_gigabytes
10.5233001708984
=> nil



John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : (e-mail address removed)
New Zealand

----------------------------------------------------------------------
=begin rdoc
This stuff can depend on the exact version of linux you have.
Ugly, I know.

__extension__ typedef unsigned long long int __u_quad_t;
__extension__ typedef __u_quad_t __fsblkcnt64_t;
__extension__ typedef __u_quad_t __fsfilcnt64_t;
__extension__ typedef struct { int __val[2]; } __fsid_t;

struct statfs64
{
int f_type;
int f_bsize;
__fsblkcnt64_t f_blocks;
__fsblkcnt64_t f_bfree;
__fsblkcnt64_t f_bavail;
__fsfilcnt64_t f_files;
__fsfilcnt64_t f_ffree;
__fsid_t f_fsid;
int f_namelen;
int f_frsize;
int f_spare[5];
};

#define __NR_statfs64 268
#define __NR_fstatfs64 269

I dug the above info out using the follow trick....
tmp = "/tmp/struct.c"
open(tmp, 'w') do |c|
c.puts "
#define _GNU_SOURCE 1
#include <sys/syscall.h>
#include <sys/statfs.h>

struct statfs64 s;

"
end

puts `gcc -E #{tmp}`

=end

require 'pp'

class StatFs64
STRUCT_STATFS64 = [
[0, 'i', 'f_type'],
[0, 'i', 'f_bsize'],
[0, 'Q', 'f_blocks'],
[0, 'Q', 'f_bfree'],
[0, 'Q', 'f_bavail'],
[0, 'Q', 'f_files'],
[0, 'Q', 'f_ffree'],
[0, 'i', 'f_fsid0'],
[0, 'i', 'f_fsid1'],
[0, 'i', 'f_namelen'],
[0, 'i', 'f_frsize'],
[0, 'i', 'f_spare0'],
[0, 'i', 'f_spare1'],
[0, 'i', 'f_spare2'],
[0, 'i', 'f_spare3'],
[0, 'i', 'f_spare4'],
]

def syscall_pack( triplets)
template = ''
default = []
triplets.each do |value, directive, name|
default << value
template += directive
end
default.pack( template)
end

def syscall_unpack( triplets, string)
template = ''
names = []
triplets.each do |value, directive, name|
names << name
template += directive
end

result = {}
values = string.unpack( template)
names.each_with_index do |name,i|
value = values
result[name] = value
end

result
end

def initialize( path)
string = syscall_pack( STRUCT_STATFS64)
result = syscall( 268, path, string.size, string)
raise "Unexpected return value '#{result}'" unless
result == 0

@statfs64 = syscall_unpack( STRUCT_STATFS64, string)
end

def free_megabytes
(@statfs64['f_bavail'] * @statfs64['f_bsize']) / (1024 * 1024.0)
end

def free_gigabytes
free_megabytes / 1024.0
end

attr_reader :statfs64
end
 
R

Robert Klemme

I was wondering if there was something to du -h?

Not sure such thing exists. You could check RAA. If not, you can
pretty easily implement something yourself using Find and File#size or
File#stat and some additional logic that takes into account the
clustering size of the file system.

Cheers

robert
 
M

Matthew B.

For the web archive :) my slightly shorter effort, possibly more
portable, is attached. It relies on libffi being installed:

module Linux; module StatFs

# The result of a statfs operation, see "man statfs" for more
information
# on each field. We add some helper methods that deal in bytes.
#
class Result < Struct.new:)type, :bsize, :blocks, :bfree, :bavail,
:files, :ffree)
def total; blocks * bsize; end
def free; bfree * bsize; end
def avail; bavail * bsize; end
end

module Lib
extend FFI::Library
ffi_lib FFI::Library::LIBC
attach_function 'statfs64', [:string, :pointer], :int
end

# Drives the interface to the C library, returns a StatFs::Result
object
# to show filesystem information for the given path.
#
def self.statfs(path)
output = FFI::MemoryPointer.new(128)
begin
error_code = Lib::statfs64(path, output)
raise "statfs raised error #{error_code}" if error_code != 0
return Result.new(*output[0].read_array_of_long(7))
ensure
output.free
end
end

end; end

I've only tested it to see that the results tally with "df", so e.g. to
find the number of free bytes on your root, you run:

Linux::StatFs.statfs(".").free

Regards,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top