From: Ed Hynan X-Sender: ehy@evh.liii.com To: Michele Andreoli Subject: Re: du.awk Hi Michele, I did some more work on du.awk. Now, for all the implemented options, output sizes agree with the real du, but note that I've only done quick easy tests. The order of the output lines don't match. I hope that's not important. These options are still not implemented: -D, -h, -L, -m, -x. I'll put this version on the end of this message. #!/usr/bin/awk -f BEGIN { ls="/bin/ls"; lscmd = ls " -AilQRqs --color=no"; gtot = 0; opt["b"] = "blocks"; for ( i = 1; i < ARGC; i++ ) { arg = ARGV[i]; if ( arg == "--" ) { i++; break; } if ( index(arg, "-") != 1 ) break; if ( arg == "-a" || arg == "--all" ) { opt["a"] = 1; } else if ( arg == "-b" || arg == "--bytes" ) { opt["b"] = "bytes"; } else if ( arg == "-k" || arg == "--kilobytes" ) { opt["k"] = 1; } else if ( arg == "-c" || arg == "--total" ) { opt["c"] = 1; } else if ( arg == "-l" || arg == "--count-links" ) { opt["l"] = 1; } else if ( arg == "-s" || arg == "--summarize" ) { opt["s"] = 1; } else if ( arg == "-S" || arg == "--separate-dirs" ) { opt["S"] = 1; } else { eprint("bad option: " arg); exit(1); } } if ( opt["a"] && opt["s"] ) { eprint("cannot both summarize and show all entries"); exit(1); } for ( ; i < ARGC; i++ ) { sub("/$", "", ARGV[i]); doarg(ARGV[i]); } if ( opt["c"] ) prnitem(gtot,"total"); exit(0); } function doarg(arg , basecmd, cmd, tmp) { basecmd = lscmd " "; if ( opt["k"] ) basecmd = basecmd "-k "; cmd = basecmd "-d " arg; initdata(); if ( (cmd | getline) < 1 ) { eprint("failed checking " arg); close(cmd); return; } close(cmd); tmp = substr($3, 1, 1); if ( tmp == "d" ) { newdir(arg); newitem(arg, $1, $2, $3, $4, $7); cmd = basecmd arg; while ( (cmd | getline) > 0 ) { if ( $0 == "" ) continue; if ( $0 ~ /^.*[^\"]:$/ ) { sub(":$", "", $0); newdir($0); } else if ( $1 !~ /^total$/ ) { sub("^\"", "", $11); sub("\".*?", "", $11); newitem($11, $1, $2, $3, $4, $7); } } close(cmd); prndir(arg); } else { if ( opt["b"] == "bytes" ) tmp = $7; else tmp = $2; prnitem(tmp, arg); } } function initdata() { delete dirs; delete dtree; delete hlinks; delete items; delete entries; delete dnames iidx = 0; didx = -1; } function newdir(name) { dnames[++didx] = name; dirs[name] = 0; } function newitem(name, inode, blocks, mode, links, bsize , t) { t = substr(mode, 1, 1); items[iidx] = didx; items["names",iidx] = name; entries["inode",didx,iidx] = inode; entries["blocks",didx,iidx] = blocks; entries["bytes",didx,iidx] = bsize; entries["type",didx,iidx] = t; if ( t == "d" ) { if ( opt["b"] == "bytes" ) items[dnames[didx] "/" name] = bsize; else items[dnames[didx] "/" name] = blocks; } else if ( links > 1 ) { hlinks[inode] = \ hlinks[inode] SUBSEP dnames[didx] "/" name; } iidx++; } function prndir(top , tot, n, nd, ts, tn, ta) { tot = 0; for ( n = 0; n < iidx; n++ ) { nd = items[n]; tn = dnames[nd] "/" items["names",n]; ts = entries[opt["b"],nd,n]; if ( !opt["l"] && (entries["inode",nd,n] in hlinks) ) { split(hlinks[entries["inode",nd,n]], ta, SUBSEP); # only count 1st link (index 2 in ta). if ( tn != ta[2] ) continue; } if ( entries["type",nd,n] == "d" ) { if ( !opt["S"] ) dirs[dnames[nd]] += ts; dtree[dnames[nd]] = \ dtree[dnames[nd]] SUBSEP items["names",n]; } else if ( opt["a"] ) { dirs[dnames[nd]] += ts; prnitem(ts, tn); } tot += ts; } if ( !opt["S"] ) fixdirtotals(top); if ( !opt["s"] ) for ( n = 1; n <= didx; n++ ) prnitem(dirs[dnames[n]] + items[dnames[n]], dnames[n]); gtot += tot; if ( opt["S"] ) prnitem(dirs[top] + entries[opt["b"],0,0], top); else prnitem(tot, top); } function fixdirtotals(dir , ta, tn, i) { split(dtree[dir], ta, SUBSEP); for ( i = 2; (i in ta); i++ ) { tn = dir "/" ta[i]; fixdirtotals(tn); dirs[dir] += dirs[tn]; } } function prnitem(size, name) { printf("%-7lu %s\n", size, name); } function eprint(msg) { # If necessary remove the >"/dev/stderr", but /dev/stderr should work. print "" ARGV[0] ": " msg >"/dev/stderr"; }