[comp.lang.perl] a more find-like version of dodir

juha@ttds.tds.kth.se (Juha Sarlin) (09/13/90)

Larry Wall's dodir doesn't work exactly like the unix-command find:

  - You always have to start in '.' and cannot give a list of files;
    this could be fixed with something like:
	chop($cwd = `pwd`);
	grep(chdir $_ && (&dodir($_), chdir $cwd), @files);

  - It always skips the starting directory. Eg, &dodir('.') doesn't
    print '.'.

Here is dofiles, a modified version of dodir that fixes these problems
and also makes errors in chdir and opendir non-fatal:

#!/usr/local/bin/perl
# Recursive directory walker.
# Prints all pathnames given on the command line. If any of them
# are directories their contents are printed recursively.
# This is like: find ${*-.} -print

unshift(@ARGV, '.') if $#ARGV < $[;
&dofiles('', 0, @ARGV);

sub dofiles {
    local($dir,$nlink,@filenames) = @_;
    local($dev,$ino,$mode);

    if ($nlink == 2) {			# this dir has no subdirectories
	for (@filenames) {
	    $name = $dir.$_;
	    print $name,"\n";
	}
    }
    else {				# this dir has subdirectories
	local($back) = '..';
	chop($back = `pwd`) unless $nlink;	# first time
	for (@filenames) {
	    $name = $dir.$_;
	    print $name,"\n";

	    if (($dev,$ino,$mode,$nlink) = lstat($_)) {
		next unless -d _;
		if (chdir $_) {
		    if (opendir(DIR,'.')) {
			(readdir(DIR) =~ /^\.$/ && readdir(DIR) =~ /^\.\.$/)
			  || die "Directory $name doesn't start with . and ..";
			$name .= '/' unless /\/$/;
			&dofiles($name, $nlink, readdir(DIR));
		    }
		    else {
			print STDERR "Can't open $name: $!\n";
		    }
		    chdir $back;
		}
		else {
		    print STDERR "Can't cd to $name: $!\n";
		}
	    }
	    else {
		print STDERR "$name: $!\n";
	    }
	}
    }
}
--
Juha Sarlin   juha@tds.kth.se