graphical representation of `du`

Австин Ким avstin at mail.ru
Tue Apr 5 00:12:43 UTC 2011


Sun, 3 Apr 2011 20:57:24 +0100 письмо от Chris Rees <utisoft at gmail.com>:

> On 3 April 2011 20:26, Австин Ким <avstin at mail.ru> wrote:
> > Sun, 03 Apr 2011 12:01:24 +0200 письмо от David Demelier
> <demelier.david at gmail.com>:
> >
> >> On 02/04/2011 19:30, Chris Rees wrote:
> >> > On 2 April 2011 18:22, Chris Rees<utisoft at gmail.com>  wrote:
> >> >> On 2 April 2011 18:07, Mike Jeays<mike.jeays at rogers.com>  wrote:
> >> >>> On Sat, 2 Apr 2011 17:15:04 +0100
> >> >>> Chris Rees<utisoft at gmail.com>  wrote:
> >> >>>
> >> >>>> du -h . | awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' |
> >> >>>> awk '{print($2" ["$1"]");}' | sed -e 's,[^-][^/]*/,--,g' -e 's,^,|,'
> >> >>>
> >> >>>
> >> >>> I confess to being impressed...
> >> >>>
> >> >>
> >> >> Yeah, but perhaps I should have used sed instead of the second awk;
> >> >> fewer processes:
> >> >>
> >> >> du -h | awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' | sed
> >> >> -e 's,^[^1-9]*\([^___CTRL-V+TAB______]*\)____CTRL-V+TAB_____*\(.*\)$,\2
> >> >> \[\1\],;s,[^-][^/]*/,--,g;s,^,|,'
> >> >>
> >> >> That does exactly the same --  where I've put ____CTRL-V+TAB______ you
> >> >> have to type Ctrl-V, then a literal [::tab::] key; BSD sed doesn't do
> >> >> \t.
> >> >>
> >> >> Chris
> >> >>
> >> >
> >> > Final version:
> >> >
> >> > http://www.bayofrum.net/~crees/graphical_du.sh
> >> >
> >> > Maybe I should port it...
> >> >
> >>
> >> Thanks! This rocks! :-)
> >>
> >
> > What a fun thread :)
> >
> > Here's my two cents, written as an sh(1) function that you can tack on to
> the end of your .profile or .shrc:
> > (Caveats:  I'm writing this on a Mac OS X machine, not on a FreeBSD machine,
> at the moment, but hopefully this'll still work.
> > Also, the following will mess up if you have directories whose names begin
> with "|".)
> >
> > # dg:  `du--graphical'
> > # Usage:  dg [dir ...]
> > # Based on script by Chris Rees
> > # 1459 Sunday, 3 April 2011
> >
> > dg ( ) {
> >  du -h "$@" |
> >    awk '{FS="\t"; print $2"\t["$1"]"}' |
> >    sort |
> >    sed -e 's:[^/]*/:| :g' -e 's:\(^\(| \)*\)| \([^|].*\):\1+-\3:'
> >  return
> >  }
> 
> I used the awk a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--]  etc to
> reverse the order, rather than alphabetise it because it's quicker:
> 
> $ du -h . | time sort >/dev/null 2>time
> $ cat time
> 8.17 real         0.03 user         0.00 sys
> $ du -h . | time awk '{a[i++]=$2} END { for (j=i-1; j>=0;) print
> a[j--] }' >/dev/null 2>time2
> $ cat time2
> 7.77 real         0.14 user         0.00 sys
> 
> YMMV of course!
> 
> Chris

I can't argue with that.  If you're a sysadmin and are managing a large system,
the sort could take some time.  On the other hand, there are times when a sort
might be useful.  Then again, you could always just comment that line out :)

Which reminds me, my sort line above may not sort intuitively in the case where
directory names contain characters that precede / in the ASCII character set;
for example, "mydir-old" sorts before "mydir/" in ASCII.  A quick kludge is to
translate slashes into, oh I don't know, say carriage returns before the sort,
and then translate them back after the sort, as is done below.  An inelegant
and inefficient solution, but it works.  However, I'm going out on a limb by
assuming users won't be running this script under MS-DOS, where this kludge
wouldn't work.

Another problem with my script above is that in some cases, if you run it on
multiple arguments, e. g., "dg dir1/subdir dir2/subdir," you can't tell from
the output to which parent directory the subdirectory refers; to deal with
this problem, the revised version below runs du on each argument one at a time.
However, I ended up having to duplicate the main command in the script (once
for "dg" with arguments, and once without), 'cause I'm not clever enough to
figure out a way to combine the two cases into one in time to post this.

I also had a redundant [^|] in the sed expression which I took out; it
shouldn't be necessary, although the script will still mess up if any directory
names start with "| ".

Finally, the revised version is repackaged as a proper sh(1) script like your
original script rather than as a function, to make it independent of a user's
particular shell.  Obviously further variations and improvements could be made.

Again I'm away from my FreeBSD machine and am writing this on a Mac OS X
machine; hopefully I didn't break anything.

#!/bin/sh
#
# dg:  `du--graphical'
# Usage:  dg [dir ...]
#
# Based on script by Chris Rees
# 1459 Sunday, 3 April 2011
#
# Modified:  1900 Monday, 4 April 2011

if [ "$1" ]
   then for i in "$@"
            do if [ "$2" ]
                  then echo
                       echo $i:
               fi
               du -h "$i" |
                  awk '{FS="\t"; print $2"\t["$1"]"}' |
                  tr / '\r' |
                  sort |
                  tr '\r' / |
                  sed -e 's:[^/]*/:| :g' -e 's:\(^\(| \)*\)| \(.*\):\1+-\3:'
        done
   else du -h |
           awk '{FS="\t"; print $2"\t["$1"]"}' |
           tr / '\r' |
           sort |
           tr '\r' / |
           sed -e 's:[^/]*/:| :g' -e 's:\(^\(| \)*\)| \(.*\):\1+-\3:'
fi


More information about the freebsd-questions mailing list