res (01/25/83)
There have been several programs posted to the net to get a listing of the structure of a directory system. The following shell also generates a simple form of such a listing, without all the grand and glorious information about access privileges, size, et al. I have called it catalog ... since it is recursive you should name it likewise, or change the recursive invocation. The instructions are reasonably complete. # catalog - produce complete file structure list from directory # # Parameters: 1: directory name (optional) # 2: indentation string (empty on first call) # # Produces on standard output the file structure emanating from # the current directory. Each descent into a subdirectory # is indicated by further indentation. Directories are indicated # by surrounding [], and executable files are prefaced with a *. # if [ "$1" = "" ] then echo "file structure from directory `pwd`" date echo "\n\n" fi if [ "$1" != "" ] then cd $1 fi for i in * do if test -d $i then echo "${2}[ $i ]" catalog $i "$2 . " else if [ "$i" != '*' ] then if test -x $i then echo "${2} *$i " else echo "${2} $i " fi fi fi done Some sample output follows: file structure from directory /n1/res/bin Tue Jan 25 12:49:44 CST 1983 *fort fortdata *sh [ source ] . fort.c . sh.c . soxpnd.c *soxpnd temp
nyuada (01/28/83)
Would someone please explain to me why everbody is writing shell scripts that do recursive directory listings? How are they significantly better than "ls -R"? If you want to do more general things than list files, but do it recursively to a directory tree, you can use "find". It's syntax is a little odd and its semantics are kludgy so I wrote a csh script that executes an arbitrary one-line csh command repeatedly (and, optionally, recursively) on a list of files/directories. It follows, beginning with a comment containing the documentation. Hope this is useful to some of you. # # Loop on files # # Synopsis: # loopf [-R[ad]] cmd file... # # Executes cmd once for each file, arranging that $1 will be set to the file # name during execution of cmd. $2, $3, ... will be set to the remaining # (unprocessed) args. If no files are given, "." is used. If there are no # occurrences of $ in the cmd, " $1" is appended to it causing the cmd to be # executed with each file as a single parameter. If -R is set, the cmd is not # executed on directory files, but the names of such directories are printed # and they are recursively processed. With -Rd, the cmd is executed on direc- # tories instead of printing them, then they are recursively processed. With # -Ra or -Rad, files beginning with . (except . and ..) are processed also, but # note that "loopf -Ra cmd *" will not process such files in the current direc- # tory, because the * is expanded before loopf is invoked (use "loopf -Ra cmd # ."). All cmd executions (at same recursive level) get executed in a single # csh process. Hence csh variables may be set and tested usefully. Also, to # control execution, break, exit and continue may be used within the cmd. # # Examples: # loopf 'od -X' * /* prints hex dump of all # /* files in current dir */ # loopf 'cp $1 $1.back' a b /* causes: cp a a.back */ # /* cp b b.back */ # loopf 'echo $#argv ; break' * /* prints # files in dir */ # loopf 'if ($2 != "") mv $2 $1' tmp a b tmp # /* swaps files a and b */ # loopf -R 'if ($1 =~ *.c) ls -l $1' / /* lists all .c files */ # loopf -Rd\ # 'echo $1; if (-d $1) mkdir dest/$1 ; if (! -d $1) cp $1 dest/$1' * # /* recursively copies current # dir to dest dir, making any # neccessary subdirs. */ # loopf \ # 'if (! $?sum) @ sum=0 ; @ sum = $sum + $1 ; if ($2 == "") echo $sum' \ # $vector /* prints +/vector (plus */ # /* reduction of $vector) */ # set nonomatch set recurse = "false" set dodirs = "false" set dodots = "false" if ("$1" =~ -R*) then # echo "Recursive loop" set switch = "$1" set recurse = "true" if ("$1" =~ -R*d*) then set dodirs = "true" endif if ("$1" =~ -R*a*) then set dodots = "true" endif shift endif if ($#argv == 0) then echo "Usage: loopf [-R[ad]] cmd file..." exit else if ($#argv == 1) then set argv = ("$argv[1]" ".") endif if ("$1" =~ *\$*) then set cmdarg = "$1" else set cmdarg = "$1"' $1' endif alias cmd 'set argv=(\!*) ; '"$cmdarg" set files = ($argv[2-]:q) set needblnk = "false" while ($#files > 0) if ($recurse == "true" && -d $files[1]) then if ($dodots == "true") then set dircnts = ( {${files[1]}/.[0-z],${files[1]}/}* ) else set dircnts = ( ${files[1]}/* ) endif if ("$dircnts" =~ *\*) set dircnts = () if ($dodirs == "true") then cmd $files else if ($needblnk == "true") echo " " echo "${files[1]}:" endif if ($#dircnts > 0) then loopf "$switch" "$cmdarg" $dircnts:q if ($dodirs == "false") echo " " set needblnk = "false" endif else cmd $files set needblnk = "true" endif shift files end