From: utzoo!decvax!harpo!floyd!cmcl2!cmcl1!nyuada Newsgroups: net.unix-wizards Title: Re: A Shell Procedure for Directory Structure Listing Article-I.D.: cmcl1.121 Posted: Thu Jan 27 18:45:42 1983 Received: Sun Jan 30 10:25:43 1983 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