views:

39

answers:

2

How do i display directory sizes in a sorted manner in Unix while listing only innermost sub-directories? For example, I don't want get to something like this -

100270480        /a/b/BP/b/bat/qc3  
100270416        /a/b/BP/b/bat/qc3/logs  
99020464        /a/b/BP/b/bat/qc3/logs/i  
99005456        /a/b/BP/b/bat/qc5  
99005408        /a/b/BP/b/bat/qc5/logs  
97726832        /a/b/BP/b/bat/qc5/logs/i  

I just want -

99020464        /a/b/BP/b/bat/qc3/logs/i  
97726832        /a/b/BP/b/bat/qc5/logs/i
A: 
du -s /a/b/BP/b/bat/qc*/logs/i | sort -n
Ignacio Vazquez-Abrams
A: 

My comment to the question notes:

For example, suppose /a/b/c contains N blocks worth of files, and /a/b/d contains M blocks worth of files, du -s would show that /a/b contains N + M + P blocks, where P is the size of the files contained directly in /a/b and not in a sub-directory. Clearly, post-processing the output of du -s would give you the correct answer.

The following Perl script, subsum.pl, does the hard work described, assuming the input is in the correct order:

#!/usr/bin/env perl

use strict;
use warnings;
use File::Basename;
use constant debug => 0;

my %sizes;
my %cumsub;

while (<>)
{
    chomp;
    my($size, $name) = split;
    printf "#-1-  %10d   %s\n", $size, $name if debug;
    $cumsub{$name} = 0 unless defined $cumsub{$name};
    $sizes{$name} = $size - $cumsub{$name};
    my $base = dirname($name);
    $cumsub{$base} += $size;
    printf"#-2-  %10d  %s\n", $cumsub{$base}, $base if debug;
}

for my $key (keys %sizes)
{
    print "$sizes{$key} $key\n";
}

The full command pipeline might be:

du -s /a/b/BP/b/bat/qc[35] |
sort -r -k 2 |
perl subsum.pl |
sort -n -k 1 -r

Given the output shown in the question, it produces the answer (biggest directories first):

99020464 /a/b/BP/b/bat/qc3/logs/i
97726832 /a/b/BP/b/bat/qc5/logs/i
1278576 /a/b/BP/b/bat/qc5/logs
1249952 /a/b/BP/b/bat/qc3/logs
64 /a/b/BP/b/bat/qc3
48 /a/b/BP/b/bat/qc5

Is that what you wanted?

Jonathan Leffler