Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

disk space utilization

by ministry (Scribe)
on Apr 08, 2005 at 19:15 UTC ( #446123=perlquestion: print w/replies, xml ) Need Help??

ministry has asked for the wisdom of the Perl Monks concerning the following question:

What is going to be the easiest way to find out how much disk space capacity has been utilized on a particular slice? For example, when I attempted this in a shell script, my syntax was as follows (to find the root partitions capacity):

SLICE1=`/bin/df -k|/bin/egrep "/^"|/bin/awk '{print $5}'`

Here I just used the output of a /bin/df -k and printed out the one value I was looking for. Should I simply pipe a df -k from the shell into my perl script, and trim up the output a bit, or is there a better way?

Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.

Replies are listed 'Best First'.
Re: disk space utilization
by saintmike (Vicar) on Apr 08, 2005 at 20:06 UTC
Re: disk space utilization
by xorl (Deacon) on Apr 08, 2005 at 19:53 UTC
Re: disk space utilization
by ambrus (Abbot) on Apr 08, 2005 at 20:08 UTC

    I wonder how "/^" could match anything in the command you've given. Anyway, df /foo/bar lists the data only for the filesystem that contains the file /foo/bar (which can be the root file system, or a fs mounted on /foo or on /foo/bar).

    The pure perl solution is to use ustat or statfs:

    sub __NR_statfs () { 99 }; $file = "/"; $s = pack "x256"; -1 == syscal +l(__NR_statfs, "".$file, $s) and die "error statfs: $!"; (undef, $bsi +ze, undef, $bfree, $bavail) = unpack "l!5", $s; print $bavail*$bsize/ +1024, " kilobytes available\n";

    Update: statfs is linux-specific (Update: except not really, but the structure might be different, I don't know). Ustat might be usable on other systems too.

    Update 2006 sep: note that system call numbers are different on every architecture (OS and CPU type). You have to look up the syscall number of your architecture.

Re: disk space utilization
by gam3 (Curate) on Apr 08, 2005 at 20:18 UTC
    This may be one of the few cases where awk is the correct solution.
    df -P | awk '/^\//{printf("%5s %s\n", $5, $6);}'
    df -P | perl -ne 'printf("%5s %s\n", (split(/\s+/, $_))[4, 5])'
    If you want to do a lot more formating; then I would write a complete perl program.

    use Filesys::Statvfs; open MOUNTED, "</proc/mounts" || die "Could not open /proc/mounted\n"; while (my $mountpoint = <MOUNTED>) { my ($bsize, $blocks, $bfree, $bavail, $files, $ffree, $namelen); my $path = (split(/\s+/, $mountpoint))[1]; if (1) { ($ftype, $bsize, $blocks, $bfree, $files, $ffree, $bavail) = statvfs("/tmp"); } else { # This is not very portable my $buf = "\0"x64; syscall(99, $path, $buf) == 0 or die "Bad mountpoint $path\n"; ($bsize, $blocks, $bfree, $bavail, $files, $ffree, $namelen) = unpack "x4 L6 x8 L", $buf; } next unless $blocks; print <<EOT; path: $path Optimal transfer block size: $bsize Blocks in file system: $blocks Blocks free: $bfree (${\(int $bfree/$blocks*100)} +%) User blocks available: $bavail (${\(int $bavail/$blocks*100 +)}%) Inodes: $files Free inodes: $ffree (${\(int $ffree/$files*100)}% +) EOT }
    -- gam3
    A picture is worth a thousand words, but takes 200K.
Re: disk space utilization
by sh1tn (Priest) on Apr 08, 2005 at 19:41 UTC
    df -k | perl -ne '/(\S+\s+){4}(\S+)/&&print$2.$/' -

      Perl's "-a" command-line option allows you to pretend that you're using something that resembles "awk" (that's why it's "-a") -- differences between "perl -a" and "awk" are that perl uses @F where awk uses $1,$2,..., and the first token on the line is $F[0] instead of $1:
      df -k | perl -lane 'print $F[3]'
      (the "-l" option helps make line-feed handling more like awk as well). I presume this still doesn't do exactly what the OP intended, since it prints a line of output for every line of input from "df -k"; but the OP's use of "grep '/^' " seems odd -- not sure what's intended by that.

      To limit the output to a particular line, one can cite the target path as an arg to "df", and/or use a condition in the perl script:

      df -k / | perl -lane 'print $F[3] if /\d/' # skips column headings # or just: df -k | perl -lane 'print $F[3] if m{/$}' # only prints value for "/ +"
        Thanks for the info graff, the use of an expression grep "/^" in the middle of my arguement will only report back the line of output in the df -k that has a slash that is immediately followed by an end of line tag (anchor)- thereby only returning the root partition, as opposed to only doing a basic grep for a slash, which will return every slice starting with a slash (working in ksh).
        Is there any way I can incorporate your 'one-liner' into my script? As this is only one function out of several that needs to be performed.

        Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://446123]
Approved by jfroebe
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2023-06-08 15:26 GMT
Find Nodes?
    Voting Booth?
    How often do you go to conferences?

    Results (34 votes). Check out past polls.