[comp.unix.wizards] Subdirectory listing

olasov@cs.columbia.edu (Benjamin Olasov) (05/20/89)

I'm interested in finding a unix command usage that will return the complete
path names of all subdirectories below a given directory, so that, given a
directory tree like this:


                                  |----- /user1
                                  |
                  /               |
             /sys --              |----- /user2 ----- /data ----- /bin
           /      \               |
         /                        |
       /                          |----- /user3 ----- /docs
/files ----- /home ----- /users --|
       \                          |
         \                        |----- /user4
           \                      |
             /vol                 |
                                  |----- /user5
                                  |  
                                  |
                                  |----- /user6 ----- /mail
                                                \
                                                  \
                                                    \ /hacks


the command would take the directory of interest as its argument, as in:

$ mycommand /files/home/users

and return the subdirectories in the format:

/files/home/users/user1
/files/home/users/user2
/files/home/users/user2/data
/files/home/users/user2/data/bin
/files/home/users/user3
/files/home/users/user3/docs
/files/home/users/user4
/files/home/users/user5
/files/home/users/user6
/files/home/users/user6/mail
/files/home/users/user6/hacks

What's the easiest way to do this?

Ben

mani@csun1.UUCP (Maninder Chawla) (05/21/89)

From article <215@cs.columbia.edu>, by olasov@cs.columbia.edu (Benjamin Olasov):
> 
> 
> I'm interested in finding a unix command usage that will return the complete
> path names of all subdirectories below a given directory, so that, given a
/* stuff deleted */

I am sure there are lots of ways to do this. Here's a recursive C program to 
do it. It has its own limitations like maximum path length. I have a tree 
printing version of it too. It uses curses, terminfo etc.
The listing for syserr.h is also included.


--mani

mani@csun1.cs.uga.edu
mani%csun1.cs.uga.edu@gatech.edu
 

_____________________________________________________________________________


# include <string.h>
# include <stdio.h>
# include <sys/types.h>
# include <sys/dir.h>
# include <sys/stat.h>
# include <"syserr.h">
 
char *path, *pname;
int cnt;
main()
{
path=(char *)malloc(100);
pname=(char *)malloc(100);
strcpy(path,".");cnt = 0;
workout();
}
 
workout()
{
   struct stat *sbuf;
   struct direct *dlink;
   int  nread;
   char *dname, *temp;
   DIR *dirp;
 
  sbuf=(struct stat *)malloc(sizeof(struct stat));
  dlink=(struct direct *)malloc(sizeof(struct direct));
  dname=(char *)malloc(20);
 
  if ((dirp=opendir(path)) == NULL ) syserr("open root");
  while ((dlink=readdir(dirp)) != NULL)
  {
      if ( !dlink->d_ino ) continue;
      strcpy(dname,dlink->d_name);
      if (!strcmp(dname,".") || !strcmp(dname,"..")) continue;
      strcpy(pname,path);strcat(pname,"/");strcat(pname,dname);
      if (stat(pname, sbuf)== -1) syserr("stat");
      if (((sbuf->st_mode) & S_IFMT) != S_IFDIR) continue;
      printf("%d %s is a directory. Path is %s\n",cnt++,dname,pname);
      strcat(path,"/"); strcat(path, dname); workout();
   }
   closedir(dirp);
   if ((temp=strrchr(path,'/'))!=NULL) *temp = '\0';
}

/* end of program */
_________________________________________________________________________ 
syserr.h listing

# include <stdio.h>
syserr(msg)      /* print system call error message & quit */
char *msg;

{ 
	 extern int errno, sys_nerr;
	 extern char *sys_errlist[];

	 fprintf(stderr, "ERROR: %s (%d", msg, errno);
	 if (errno > 0 && errno < sys_nerr )
		fprintf(stderr,";%s)\n", sys_errlist[errno]);
     else fprintf(stderr,")\n");
	 exit(1);
}
	   

charlie@mica.stat.washington.edu (Charlie Geyer) (05/21/89)

In article <215@cs.columbia.edu> olasov@cs.columbia.edu (Ben Olasov) writes:

>I'm interested in finding a unix command usage that will return the complete
>path names of all subdirectories below a given directory

  find directoryname -type d -print

wcf@psuhcx.psu.edu (Bill Fenner) (05/21/89)

In article <215@cs.columbia.edu> olasov@cs.columbia.edu (Ben Olasov) writes:
|I'm interested in finding a unix command usage that will return the complete
|path names of all subdirectories below a given directory

find /files/home/users -type d -print

  Bill
-- 
   Bitnet: wcf@psuhcx.bitnet     Bill Fenner       | "Yesterday starts
  Internet: wcf@hcx.psu.edu                        |  tomorrow; tomorrow
 UUCP: {gatech,rutgers}!psuvax1!psuhcx!wcf         |  starts today"
Fido: Sysop at 1:129/87 (814/238 9633) \hogbbs!wcf |       -- Marillion

bzs@bu-cs.BU.EDU (Barry Shein) (05/21/89)

>What's the easiest way to do this?
>
>Ben

	find dirname -print

-- 
	-Barry Shein, Software Tool & Die

There's nothing more terrifying to hardware vendors than
satisfied customers.

wlm@archet.UUCP (William L. Moran Jr.) (05/22/89)

In article <215@cs.columbia.edu> olasov@cs.columbia.edu (Ben Olasov) writes:
>
>
>I'm interested in finding a unix command usage that will return the complete
>path names of all subdirectories below a given directory, so that, given a
>directory tree like this:
... deleted
>What's the easiest way to do this?

Why not simply use find /foo -type d -print ? Unless I misunderstand what
you are trying to do, this does it. It'll produce stuff like:
/foo/bar
/foo/baz
/foo/baz/beep
				Bill Moran



-- 
arpa: moran-william@cs.yale.edu or wlm@ibm.com
uucp: uunet!bywater!acheron!archet!wlm or decvax!yale!moran-william
-------------------------------------------------------------------------------
To keep on running, try with all our might,
But in the midst of effort faint and fail;

rbj@dsys.icst.nbs.gov (Root Boy Jim) (05/23/89)

? In article <215@cs.columbia.edu> olasov@cs.columbia.edu (Ben Olasov) writes:
? |I'm interested in finding a unix command usage that will return the complete
? |path names of all subdirectories below a given directory

? find /files/home/users -type d -print

Almost. Don't forget to pipe it to `sort', as find doesn't.
And BZS forgot that he asked for directorys only.

One thing I recently discovered is that find takes multiple directorys
before the options: find /here /there /everywhere -dothis -dothat ...

	Root Boy Jim is what I am
	Are you what you are or what?

guy@auspex.auspex.com (Guy Harris) (05/23/89)

>I am sure there are lots of ways to do this. Here's a recursive C program to 
>do it.

Yes, there are lots of ways; using the already-written "find" command is
far easier than writing your own program to do the same thing....

spl@mcnc.org (Steve Lamont) (05/23/89)

In article <19707@adm.BRL.MIL> rbj@dsys.icst.nbs.gov (Root Boy Jim) writes:
>? In article <215@cs.columbia.edu> olasov@cs.columbia.edu (Ben Olasov) writes:
>? |I'm interested in finding a unix command usage that will return the complete
>? |path names of all subdirectories below a given directory
>
>? find /files/home/users -type d -print
>
>Almost. Don't forget to pipe it to `sort', as find doesn't.

.... Um... am I missing something or doesn't 

			du -a .

or

			du -a your_favorite_directory

do all this good stuff without the fuss and muss?  Is this really a
"wizards" type question?  


-- 
							spl
Steve Lamont, sciViGuy			EMail:	spl@ncsc.org
North Carolina Supercomputing Center	Phone: (919) 248-1120
Box 12732/RTP, NC 27709

ray3rd@ssc-vax.UUCP (Ray E. Saddler III) (05/23/89)

In article <215@cs.columbia.edu>, olasov@cs.columbia.edu (Benjamin Olasov) asks:
> 
> I'm interested in finding a unix command usage that will return the complete
> path names of all subdirectories below a given directory, so that, given a
> directory tree like this:
> 
> 				( Example deleted )
> 
> the command would take the directory of interest as its argument, as in:
> 
> $ mycommand /files/home/users
> 
> and return the subdirectories in the format:
> 
> /files/home/users/user1
> /files/home/users/user2
> /files/home/users/user2/data
> /files/home/users/user2/data/bin
> /files/home/users/user3
> /files/home/users/user3/docs
> /files/home/users/user4
> /files/home/users/user5
> /files/home/users/user6
> /files/home/users/user6/mail
> /files/home/users/user6/hacks
> 
> What's the easiest way to do this?
> 

Give this script a spin around the block:

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#!/bin/sh
#
	if [ $# = 0 ]
	then 
	  echo "Usage: mycommand <dir>"
	  #
	  # You could ask for the directory here, or assume a
	  # default, if you so desired...I opt to exit non-zero
	  #
	  exit 1
        else
	  for I in $*
	  do
	    find $I -type d -exec ls -d {} \;
          done
        fi
        exit 0

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Sample usages:

$ mycommand
Usage: mycommand <dir>
$
$ mycommand /user4/ray3rd /user4/law /user4/jsk /user4/markb
/user4/ray3rd
/user4/ray3rd/SYTEK
/user4/ray3rd/HUMOR
/user4/ray3rd/bin
/user4/ray3rd/clock
/user4/ray3rd/VTREE
/user4/ray3rd/3B1
/user4/ray3rd/block
/user4/ray3rd/CADSA
/user4/ray3rd/UUMAP
/user4/ray3rd/shartest
/user4/ray3rd/STANDARDS
/user4/law
/user4/jsk
/user4/markb
$
$ mycommand .
.
./SYTEK
./HUMOR
./bin
./clock
./VTREE
./3B1
./block
./CADSA
./UUMAP
./shartest
./STANDARDS
$
-- 
Ray E. Saddler III       |    __  __ __       __ |          UseNet
Boeing Aerospace         |   / / / //   //| //   | uw-beaver!ssc-vax!ray3rd
P.O. Box 3999 m.s. 3R-05 |  /-< / //-  // |// _  |         PhoneNet
Seattle, Wa.  98124  USA | /__//_//__ //  //__/  |      1+206-657-2824

jik@athena.mit.edu (Jonathan I. Kamens) (05/24/89)

\begin{Hugeflame}

  OK, folks, once again it's time to review briefly what newsgroup
we're in right now, and what other newsgroups are available under the
comp.unix heirarchy.

  This is COMP.UNIX.WIZARDS.  The word "wizards" at the end is
supposed to imply that the questions and discussions conducted herein
require some GREATER THAN MINIMAL level of KNOWLEDGE and EXPERIENCE
with the Unix operating system, in whatever variety, on the part of
the people asking or discussing.

  It is my firmly held opinion that the following two topics DO NOT
qualify as questions worthy of the comp.unix.wizards newsgroup:

1. "How do I delete a filename that has strange characters in it?"

2. "How to I print out the complete path names of all subdirectories
   below a given directory?"

  Let me defend each of these assertions in turn.  The first concerns
deleting a strange filename.  It is my firmly held opinion that IF YOU
CAN'T FIGURE IT OUT, YOU SHOULDN'T BE POSTING IN COMP.UNIX.WIZARDS.
Go back to comp.unix.questions.  This question has been asked and
discussed in c.u.w WAY TOO MANY TIMES, and it's getting old.

  The second complaint I mentioned above has to do with a recent
question posted to c.u.w.  It read as follows: "I'm interested in
finding a unix command usage that will return the complete path names
of all subdirectories below a given directory..."  In other words, the
person asking the question wanted to be able to do "find <dir-name>
-type d -print."

  I object to this question for two reasons.  First, THIS IS NOT A
"WIZARD"-LEVEL QUESTION!  There is nothing whatsoever difficult about
it.  It should not present a problem to anybody who knows anything at
all about Unix.  And, if it does, then IT SHOULD HAVE BEEN POSTED IN
COMP.UNIX.QUESTIONS.

  The second complaint I have is that in response to this question, a
multitude of people posted messages TO THE NET answering it.  Many of
them were wrong or silly over-answers to a simple question, and ALL of
them should have been sent in private E-mail for the person who asked
the question to summarize.  Let's look at the answers to this question
which were posted (names omitted to protect the guilty):

1: I am sure there are lots of ways to do this. Here's a recursive C
   program to do it. It has its own limitations like maximum path
   length. I have a tree printing version of it too. It uses curses,
   terminfo etc.  The listing for syserr.h is also included.

   [incredible overkill C program to do what "find <dir> -type d
   -print" does already]

Surely you can't be serious!  Has this guy ever heard of find(1)?

2: find directoryname -type d -print

OK, this is correct answer number one.

3: find dirname -print

This is close, but it ignores the fact that the person who asked the
question only wanted to list directories, not files.

4: find /files/home/users -type d -print

This is correct answer number two.

5: Why not simply use find /foo -type d -print ?  Unless I
   misunderstand what you are trying to do, this does it....

This is correct answer number three.

6: [In response to earlier correct answers] Almost. Don't forget to
   pipe it to `sort', [sic -- punction outside of quotation marks?
   tsk, tsk :-)] as find doesn't.  And <name deleted> forgot that
   he asked for directorys [sic] only.

   One thing I recently discovered is that find takes multiple
   directorys [sic] before the options: find /here /there /everywhere
   -dothis -dothat ...

I guess we should call this a "correct answer," so this is correct
answer number four.  And I'll bet that all of us were enlightened to
find out that find can take multiple paths on which to operate.  I
guess that's what the man page means when it says that "find
pathname-list expression" is the usage, and a "pathname-list" is
"(i.e. one or more pathnames)."

7: [in response to the wonderful C program mentioned above] "Yes,
   there are lots of ways; using the already-written "find" command is
   far easier than writing your own program to do the same thing...."

Yes, this is true.  But gee, look, you haven't explained how to do it!
What a useful answer!  I'm afraid this one can't be classified as a
"correct answer."  Sorry, you don't win the prize....

8: .... Um... am I missing something or doesn't

	du -a .
   or

	du -a your_favorite_directory

   do all this stuff without the fuss and muss?  Is this really a
   "wizards" type question?

Yes, you apparently are missing something.  First of all, the guy who
asked the question only wanted directory names, not filenames, and "du
-a" lists filenames.  You would have been closer if you'd suggested
just "du" rather than "du -a."  Second, this has the unfortunate side
effect of printing the size of every directory in addition to its
path.  Did the person asking the question say he wanted to do this?
If so, then I missed it.

9: Give this script a spin around the block

   [shell script that (get a load of this!) takes each directory
   specified on the command line and runs "find <dir name> -type d
   -exec ls -d {} \;" on it]

Gee, it looks like you know about the find(1) command, but you're
completely confused.... has it occurred to you that find takes
multiple paths on the command line, or that the user asked for a
recursive listing and your script will not list recursively?  I
thought not.

  The net (pun intended) result of all this is eight responses posted
in comp.unix.wizards to a question that should never have gone into
c.u.w. in the first place.  Besides that, only four of the eight
messages provided the "correct" solution to the problem.

  CAN YOU SAY, "MAJOR TEN-TON LOSE?"  I thought so.

\end{Hugeflame}

  OK, let me reiterate the points I've tried to make in this posting:

1. Please, please, don't post a question to comp.unix.wizards unless
   you really are convinced that it's going to take the combined brain
   power of multiple "wizards" to answer your question.
   Comp.unix.questions should be your first resort in questions about
   Unix unless you are 100%, cross-your-heart-and-hope-to-day sure
   that your question is not a simple one.

2. When someone asks a question on the net and it is likely that
   several people will respond, ANSWER THE QUESTION IN E-MAIL!  DON'T
   post an answer to the net.

3. If you AREN'T a wizard, DON'T answer questions in
   comp.unix.wizards!  I hate to be blunt, but it's just plain STUPID
   (IMHO) to post a C program and a shell script to do what find(1) is
   designed to do!

  OK, I'm off my soapbox.  I feel much better now.

Jonathan Kamens			              USnail:
MIT Project Athena				410 Memorial Drive, No. 223F
jik@Athena.MIT.EDU				Cambridge, MA 02139-4318
Office: 617-253-4261			      Home: 617-225-8218

ray3rd@ssc-vax.UUCP (Ray E. Saddler III) (05/24/89)

In article <11619@bloom-beacon.MIT.EDU>, jik@athena.mit.edu (Jonathan I. Kamens) tells us:
#
# [many many bytes of flame-data deleted, except for his slam about
#  my contribution which causes him great pain: ]
# 
# 9: Give this script a spin around the block
# 

Jon, thanks for not providing my name to protect my guilt, you have
impeccable class!

#
#    [shell script that (get a load of this!) takes each directory
#    specified on the command line and runs "find <dir name> -type d
#    -exec ls -d {} \;" on it]
# 

Heh!  Whatta maroon!  Can you beleive it?!

#
# Gee, it looks like you know about the find(1) command, but you're
# completely confused.... has it occurred to you that find takes
# multiple paths on the command line, or that the user asked for a
# recursive listing and your script will not list recursively?  I
# thought not.
# 

Gee, Jon, you're right!  I *did* notice after posting, that I had a
misaligned head; I'm used to seeking a full 'ls' with full pathnames
in my find-on-the-fly usage of: find <dir> -exec ls -ldF {} \;

So, after realizing this, an attemt to 'C'ancel using readnews was
done, but I was told by the readnews software that I couldn't cancel
something I didn't create, (which wasn't the case).

I'm glad you brought my error and infraction of protocol to public
attention, you see, ignorant people like myself need to be made
examples of.

#   OK, I'm off my soapbox.  I feel much better now.

I'm so glad.  I suppose an e-mail message to you would have been
more appropriate, but I felt that a public acknowledgement [might]
be meaningful, it seems to have worked for you.  Have a nice day.

> Jonathan Kamens			              USnail:
> MIT Project Athena				410 Memorial Drive, No. 223F
> jik@Athena.MIT.EDU				Cambridge, MA 02139-4318
> Office: 617-253-4261			      Home: 617-225-8218


-- 
Ray E. Saddler III       |    __  __ __       __ |          UseNet
Boeing Aerospace         |   / / / //   //| //   | uw-beaver!ssc-vax!ray3rd
P.O. Box 3999 m.s. 3R-05 |  /-< / //-  // |// _  |         PhoneNet
Seattle, Wa.  98124  USA | /__//_//__ //  //__/  |      1+206-657-2824

root@chessene.UUCP (Mark Buda) (05/25/89)

In article <215@cs.columbia.edu>, olasov@cs.columbia.edu (Benjamin Olasov) asks:
> I'm interested in finding a unix command usage that will return the complete
> path names of all subdirectories below a given directory, so that, given a
> directory tree like this:
> 
> What's the easiest way to do this?

In article <2673@ssc-vax.UUCP> ray3rd@ssc-vax.UUCP (Ray E. Saddler III) responds:
>Give this script a spin around the block:
...
>	    find $I -type d -exec ls -d {} \;
...

Um, he asked for the *easiest* way.

find $I -type d -print

is much easier.

Mark Buda
hermit@chessene.uucp  /  hermit%chessene.uucp@uunet.uu.net
...!rutgers!bpa!vu-vlsi!devon!chessene!hermit /  devon.lns.pa.us!chessene!hermit
King of the Dancing Walnuts

PS: Anybody know why using ^Z on the console logs me out?

peter@ficc.uu.net (Peter da Silva) (05/26/89)

In article <2673@ssc-vax.UUCP>, ray3rd@ssc-vax.UUCP (Ray E. Saddler III) writes:
> 	  do
> 	    find $I -type d -exec ls -d {} \;
>           done
>         fi

Ack. At the very least:

	find $I -type d -print

But find is a hog. I generally do:

	du $I | cut -f2
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.