braswell has asked for the wisdom of the Perl Monks concerning the following question:

This is my first post so be gentle ;) I am working on a project to dump selected filesystem node attributes (e.g. uid,size,mtime,etc..) into a MySQL database for further mining. The database table defines a tree stored in Nested-Set representation.

The shell of the following code was generated using find2perl and then modified to add the pushdown stack for generating the correct left/right pairs for the nested tree node boundaries. See the code in the readmore section:
use strict; use DBI; use File::Find (); use vars qw/*name *dir *prune/; *name = *File::Find::name; *dir = *File::Find::dir; *prune = *File::Find::prune; my $dbh = DBI->connect("DBI:mysql:host=unixhost:database=fsdb", "username", "password"); my $sth = $dbh->prepare("INSERT INTO fstree (uid,size,mtime,name,lft,r +gt) VALUES(?,?,?,?,?,?)"); my $cnt = 1; my @stack; my $rowcnt; my $fs2probe = shift || die "supply a filesystem path to probe"; # Traverse desired filesystems File::Find::find({wanted => \&wanted, preprocess => \&pre, postprocess + => \&post}, $fs2probe); print "$rowcnt rows processed\n"; exit; sub wanted { my ($dev,undef,undef,undef,$uid,$gid, undef,$size,undef,$mtime) = lstat($_); if ( !($File::Find::prune |= ($dev != $File::Find::topdev)) ) +{ $rowcnt += $sth->execute($uid,$size,$mtime,$_,$cnt++,$ +cnt++) unless ( -d _ ); } } sub pre { push (@stack, [$_,$cnt++]); return @_; } sub post { my ($dev,undef,undef,undef,$uid,$gid, undef,$size,undef,$mtime) = lstat($name); my $ref = pop (@stack); $rowcnt += $sth->execute($uid,$size,$mtime,$ref->[0],$ref->[1] +,$cnt++); }
The thing to note is that in order to represent a tree correctly using the nested set model, I have to do a finddepth. But finddepth does not prune trees if they cross a filesystem boundary (even though I can still reject them in my &wanted sub). But I don't want to cross any mount points during the search as there could be NFS mounts and automount mount points, etc.) I want to traverse just the physical filesystem in question.

Is there any way for me to use File::Find to do a depth first traversal and not cross filesystems in the process?

Replies are listed 'Best First'.
Re: Using File::Find to build a Nested-Set Tree representation
by braswell (Sexton) on May 15, 2003 at 20:03 UTC
    Sorry. I cut and pasted a test case for the above code. I'm actually using File::Find::finddepth not File::Find::find to traverse. My bad.
      Long overdue update to my own question. The answer is: It doesn't matter whether you use find or finddepth to build the NSR in the way my script above is written. It still produces the correct NSR of the filesystem in the database. So if you want to prune trees AND use NSR as in my script, just use File::Find::find.