[ca.unix] Unix "tree" Command Wanted

georgeb@fai.UUCP (George Bosworth) (08/01/90)

I'm looking for a Unix version of the DOS "tree" command,
that makes a hierarchal list of subdirectories.  Not hard
to write, of course, but hoping not to spend the time.
Thanks for source or pointer to same, by email.

George Bosworth                    uunet!fai.com!georgeb
Fujitsu America, Inc.

bruceb@telesoft.com (Bruce Bergman @quasar) (08/02/90)

In article <2899@fai.UUCP>, georgeb@fai.UUCP (George Bosworth) writes:
> I'm looking for a Unix version of the DOS "tree" command,
> 
> George Bosworth                    uunet!fai.com!georgeb

Here's the puppy.  It's not great, but it does the trick.  It's intended
for BSD.  Just do a "cc -o tree tree.c" and you'll be set.  Have fun!

bruce

----- cut here -----
#include <stdio.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <sys/param.h>

#define TRUE		1
#define FALSE		!TRUE

int display_files = FALSE;

/*
*
* Tree.c -- Mimic the DOS tree command
*
* By Bruce A. Bergman, 8767 Dalewood Avenue, San Diego, CA.  92123-3926
*    bruceb@telesoft.com  (619) 457-2700 x123
* 
* Modification History
*
* Who  What       Where
* ---  ---------  -----
* bab  18-Jan-88  Initial creation.
*
* Released into the public domain as long as authorship remains intact.
*
*/

main(argc, argv)
int argc;
char *argv[];
{

	char	path[MAXNAMLEN+1];

	if (argc <= 2) {
		if (argc == 2) {
			if (strncmp(argv[1], "-f", 2) == 0) {
				display_files = TRUE;
				start_at(getwd(path));
			}
			else {
				start_at(argv[1]);
			}
		}
		else {
			start_at(getwd(path));
		}
	}
	else {
		while (--argc > 0) {
			++argv;
			if (strncmp(*argv, "-f", 2) == 0) {
				display_files = TRUE;
				continue;
			}
			strcpy(path, *argv);
			start_at(path);
			display_files = FALSE;
			if (argc > 1) {
				printf("\n");
			}
		}
	}

}

start_at(path)
char *path;
{

	DIR		*fd;

	if ((fd = opendir(path)) == NULL) {
		fprintf(stderr, "%s is not a directory\n", path);
		return;
	}

	report(path, fd);

	closedir(fd);

}

traverse(base, dir)
char *base, *dir;
{

	DIR		*fd;
	char	*p;
	int		b_len,
			d_len;

	if ((strcmp(dir, ".") == 0) || (strcmp(dir, "..") == 0)) {
		return;
	}

	b_len = strlen(base);
	d_len = strlen(dir);

	if ((p = (char *)malloc(b_len+d_len+2)) == 0) {
		fprintf(stderr, "malloc failure in traverse\n");
		exit(0);
	}

	strcpy(p, base);
	*(p+b_len) = '/';
	strcpy(p+b_len+1, dir);
	*(p+b_len+d_len+1) = '\0';

	if ((fd = opendir(p)) != NULL) {
		report(p, fd);
		closedir(fd);
	}

}

report(path, fd)
char *path;
DIR *fd;
{

	struct direct *buf;
	struct stat   sbuf;
	char	*p;
	int		len,
			got_one;

	len = strlen(path);

	if ((p = (char *)malloc(len+MAXNAMLEN+2)) == 0) {
		fprintf(stderr, "malloc failure in report\n");
		exit(0);
	}

	strcpy(p, path);
	*(p+len) = '/';

	printf("Path: %s\n", path);
	printf("Sub-directories: ");

	got_one = FALSE;

	while ((buf = readdir(fd)) != NULL) {
		buf->d_name[buf->d_namlen] = '\0';
		if ((strcmp(buf->d_name, ".") == 0) || (strcmp(buf->d_name, "..") == 0)) {
			continue;
		}
		strcpy(p+len+1, buf->d_name);
		if (stat(p, &sbuf) == -1) {
			continue;
		}
		if ((sbuf.st_mode & S_IFMT) == S_IFDIR) {
			if (got_one == FALSE) {
				got_one = TRUE;
				printf("%s\n", buf->d_name);
			}
			else {
				printf("                 %s\n", buf->d_name);
			}
		}
	}

	if (got_one == FALSE) {
		printf("None\n");
	}

	if (display_files == TRUE) {
		printf("Files: ");

		got_one = FALSE;
		rewinddir(fd);

		while ((buf = readdir(fd)) != NULL) {
			buf->d_name[buf->d_namlen] = '\0';
			if ((strcmp(buf->d_name, ".") == 0) || (strcmp(buf->d_name, "..") == 0)) {
				continue;
			}
			strcpy(p+len+1, buf->d_name);
			if (stat(p, &sbuf) == -1) {
				continue;
			}
			if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
				if (got_one == FALSE) {
					got_one = TRUE;
					printf("%s\n", buf->d_name);
				}
				else {
					printf("       %s\n", buf->d_name);
				}
			}
		}

		if (got_one == FALSE) {
			printf("None\n");
		}
	}

	printf("\n");

	rewinddir(fd);

	while ((buf = readdir(fd)) != NULL) {
		buf->d_name[buf->d_namlen] = '\0';
		traverse(path, buf->d_name);
	}

}
----- cut here -----


-- 
att!   \   crash!--\            TeleSoft (bruceb@telesoft.com)
ncr-sd! \           \           5959 Cornerstone Court West
         >--ucsd!---->--telesoft!bruceb (Bruce Bergman N7HAW)
nosc!   /           /           San Diego, CA.  92121-9891
ucbvax!/   uunet!--/            (619) 457-2700 x123
All opinions are my own.    Have you hugged your horse lately?