Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!samsung!zaphod.mps.ohio-state.edu!math.lsa.umich.edu!emv From: joey@tessi.UUCP (Joe Pruett) Newsgroups: alt.sources Subject: Re: ftw (was Re: Anything faster than stat(S)? ...) Message-ID: <10299@stag.math.lsa.umich.edu> Date: 10 Dec 89 04:33:40 GMT Sender: news@math.lsa.umich.edu Reply-To: joey@tessi.UUCP (Joe Pruett) Followup-To: comp.unix.wizards Lines: 139 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 #include #include #include #include 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); }