1

In the below script. am not able to change the directory.i need the output like above 70% disk inside that directory which one is consuming more space.

#!/usr/bin/perl
use strict;
use warnings;
my $test=qx("df -h |awk \+\$5>=70 {print \$6} ");
chdir($test) or die "$!";
print $test;
system("du -sh * | grep 'G'");
AnFi
  • 10,493
  • 3
  • 23
  • 47
  • 2
    Where do you think the problem is? In the `perl` code? In the `awk` code? What is the expected output? What is the real output? – Jdamian Jun 25 '16 at 07:55
  • its not changing the direrctoy. actually I need like above 70% disk inside that disk which directory is consuming more space – suresh babu Jun 25 '16 at 09:15
  • Then why do you not swap the perl lines `chdir`and `print` in order to print the output of `df -h`? – Jdamian Jun 25 '16 at 10:10
  • 1
    Did yo u know that the `df -h` command splits long lines in two ones and then `awk` code may not work? – Jdamian Jun 25 '16 at 10:11
  • 2
    @Jdamian That's where the ’-P’ switch kicks in. – PerlDuck Jun 25 '16 at 10:52
  • 2
    I don't know perl but if calling awk from inside perl is the right thing to do then perl must have a stunning hole in it's functionality. – Ed Morton Jun 25 '16 at 11:37
  • the above script is working fine till "my $test=qx("df -h |awk \+\$5>=70 {print \$6} ");" after that not able to change directory. please help. one more whether its good use awk inside the perl script? – suresh babu Jun 25 '16 at 12:55

2 Answers2

3

No need to call awk in your case because Perl is quite good at splitting and printing certain lines itself. Your code has some issues:

  1. The code qx("df -h |awk \+\$5>=70 {print \$6} ") tries to execute the string "df -h | awk ..." as a command which fails because there is no such command called "df -h | awk". When I run that code I get sh: 1: df -h |awk +>=70 {print } : not found. You can fix that by dropping the quotes " because qx() already is quoting. The variable $test is empty afterwards, so the chdir changes to your $HOME directory.

  2. Then you'll see the next error: awk: line 1: syntax error at or near end of line, because it calls awk +\$5>=70 {print \$6}. Correct would be awk '+\$5>=70 {print \$6}', i.e. with ticks ' around the awk scriptlet.

  3. As stated in a comment, df -h splits long lines into two lines. Example:

    Filesystem           1K-blocks      Used Available Use% Mounted on
    /long/and/possibly/remote/file/system
                         10735331328 10597534720 137796608  99% /local/directory
    

    Use df -hP to get guaranteed column order and one line output.

  4. The last system call shows the directory usage (space) for all lines containing the letter G. I reckon that's not exactly what you want.

I suggest the following Perl script:

#!/usr/bin/env perl

use strict;
use warnings;

foreach my $line ( qx(df -hP) ) {
    my ($fs, $size, $used, $avail, $use, $target) = split(/\s+/, $line);
    next unless ($use =~ /^\d+\s*\%$/); # skip header line

    # now $use is e.g. '90%' and we drop the '%' sign:
    $use =~ s/\%$//;

    if ($use > 70) {
        print "almost full: $target; top 5 directories:\n";

        # no need to chdir here. Simply use $target/* as search pattern,
        # reverse-sort by "human readable" numbers, and show the top 5:
        system("du -hs $target/* 2>/dev/null | sort -hr | head -5");
        print "\n\n";
    }

}
PerlDuck
  • 5,610
  • 3
  • 20
  • 39
2
#!/usr/bin/perl
use strict;
use warnings;
my @bigd = map { my @f = split " "; $f[5] } 
           grep { my @f = split " "; $f[4] =~ /^(\d+)/ && $1 >= 70} 
           split "\n", `df -hP`;
print "big directories: $_\n" for @bigd;
for my $bigd (@bigd) {
    chdir($bigd);
    my @bigsubd = grep { my @f = split " "; $f[0] =~ /G/ }
                  split "\n", `du -sh *`;
    print "big subdirectories in $bigd:\n";
    print "$_\n" for @bigsubd;
}

I belive you wanted to do something like this.