[alt.sources] ftw

joey@tessi.UUCP (Joe Pruett) (12/10/89)

Original-posting-by: joey@tessi.UUCP (Joe Pruett)
Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)
Posting-id: 891210.0435
Posting-number: Volume TEST, Number TEST
Archive-name: descend

[This is an experimental alt.sources re-posting from the
newsgroup(s) comp.unix.wizards.
No attempt has been made to edit, clean, modify, or otherwise
change the contents of the original posting, or to contact the
author.  Please consider cross-posting all sources postings to
alt.sources as a matter of course.]

[Comments on this service to emv@math.lsa.umich.edu (Edward Vielmetti)]

A quick hack I've used in a directory traversal program is to use the
link count of . to determine how many subdirectories there are.  If .
has no subdirectories, then you don't have to stat every file name.
Since most of the files tend to be at the end of the tree, you really
save time because none of them get stat'ed.  Here's the program I use
instead of find . -print.  It puts a / at the end of directory names
so you can use egrep '/$' or the like.  It also takes a switch of
-d for depth first printout, or -h for "heighth" first printout.
You can replace the echo function with something else if you
want a canned program, but this combined with an egrep and xargs
fixes most of the problems you want to solve for a directory
tree.  Some quick timings on a sun 3/260 with local disk show:

find . -print > /dev/null			0.4u 3.3s 0:16
descend . > /dev/null				0.4u 1.8s 0:02

With 1485 files (195 of which are directories).

--------

#include <stdio.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <strings.h>

int numErrors;
int depth = 1;

int
echo(s)
char *s;
{
	printf("%s\n", s);
}

void
descend(name, command)
char *name;
int (*command)();
{
	struct stat stb;
	DIR *dirp;
	struct direct *dp;
	int ndirs;
	char buf[1024];

	if (lstat(name, &stb) != 0) {
		perror(name);
		numErrors++;
		return;
	}
	if ((stb.st_mode & S_IFDIR) == 0) {
		(void)strcpy(buf, name);
		(*command)(buf);
		return;
	}
	ndirs = stb.st_nlink - 2;
	if ((dirp = opendir(name)) == NULL) {
		perror(name);
		numErrors++;
		return;
	}
	if (depth == 0) {
		(void)strcpy(buf, name);
		(void)strcat(buf, "/");
		(*command)(buf);
	}
	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
		if (strcmp(dp->d_name, ".") == 0
		|| strcmp(dp->d_name, "..") == 0) {
			continue;
		}
		(void)strcpy(buf, name);
		(void)strcat(buf, "/");
		(void)strcat(buf, dp->d_name);
		if (ndirs) {
			if (lstat(buf, &stb) != 0) {
				perror(buf);
				numErrors++;
				continue;
			}
			if ((stb.st_mode & S_IFDIR) != 0) {
				ndirs--;
				descend(buf, command);
			} else {
				(*command)(buf);
			}
		} else {
			(*command)(buf);
		}
	}
	if (depth == 1) {
		(void)strcpy(buf, name);
		(void)strcat(buf, "/");
		(*command)(buf);
	}
	closedir(dirp);
}

main(argc, argv)
int argc;
char **argv;
{
	argc--;
	argv++;
	while (argc) {
		if ((*argv)[0] == '-') {
			switch ((*argv)[1]) {
			case 'd':
				depth = 1;
				break;
			case 'h':
				depth = 0;
				break;
			}
		} else {
			descend(*argv, echo);
		}
		argc--;
		argv++;
	}
	exit (numErrors);
}

brian@hpausla.aso.hp.com (Brian Coogan) (12/12/89)

Joe Pruett <joey@tessi.UUCP> writes in alt.sources:
> A quick hack I've used in a directory traversal program is to use the
> link count of . to determine how many subdirectories there are.

A clever trick.  Worth keeping in mind that it won't work for symbolic
links (usually you don't want it to anyway).

mvp@v7fs1.UUCP (Mike Van Pelt) (12/13/89)

I just had reason to use ftw in a program, and I thought
I'd pass this little tidbit along.  

For some reason, ftw calls stat, which returns information
on the file pointed to by a symbolic link, rather than
information about the link itself.  Sometimes you may want
to do this, but not (as in my case) when you're trying to
produce a report of disk usage.

The solution:  Supply a function stat which calls lstat.
It will be used by ld instead of the system stat.
-- 
Mike Van Pelt                     "Something is happening here,
Headland Technology/Video 7        What it is ain't exactly clear..."
...ames!vsi1!v7fs1!mvp                 -- Pons & Fleischmann