Paul Eggert writes: > > On 12/16/11 18:36, Alan Curry wrote: > > The straightforward method would be to simply the directory you intend to > > remove and keep track of the discrepancy between st_nlink and how many links > > you've seen. > > Sorry, I can't parse that. But whatever it is, it sounds like you're > talking about what one could do with a program written in C, not with > either GNU or Solaris du.
Yes, I'm saying that du is just not the tool for this job, although you've managed to twist it to fit. The "predict free space after rm -rf foo" operation can be done without searching other directories and without requiring the user to specify a list of other directories that might contain links. What you do with du is kludgy by comparison. [...] > Of course I'd never want to do that in an actual link farm: it's tricky > and brittle and could mess up currently-running builds. But the point is that > GNU du is not being inefficient here, any more than Solaris du is. > By comparison to a proper tool which doesn't do any unnecessary traversals of extra directories, your use of du is slow and brittle (if the user forgets an alternate directory containing a link, the result is wrong) and has only the slight advantage of already being implemented. Here's a working outline of the single-traversal method. I wouldn't suggest that du should contain equivalent code. A single-purpose perl script, even without pretty output formatting, feels clean enough to me. Since I've gone to the trouble (not much) of writing it, I'll keep it as ~/bin/predict_rm_rf for future use. #!/usr/bin/perl -W use strict; use File::Find; @ARGV or die "Usage: $0 directory [directory ...]\n"; my $total = 0; my %pending = (); File::Find::find({wanted => sub { my ($dev,$ino,$nlink,$blocks) = (lstat($_))[0,1,3,12]; if(-d _ || $nlink==1) { $total += $blocks; return; } if($nlink == ++$pending{"$dev.$ino"}) { delete $pending{"$dev.$ino"}; $total += $blocks; } }}, @ARGV); print "$total blocks would be freed by rm -rf @ARGV\n"; __END__ -- Alan Curry