[comp.unix.questions] Execute a command w/wildcards & recursive descent

gt0178a@prism.gatech.EDU (BURNS,JIM) (08/31/90)

Listed below is a 'C' program I wrote because I got tired of 'ls -R' and
'find' not understanding wildcards, even if quoted. Can anyone tell me how
to do something like

find . -type d -exec 'general command with wildcards and {}' \;

or any other equivalent Unix command? Obviously, I could do

find . -type d -exec scriptfile {} \;

and use $1 in the script any way I choose, but I don't want a different
script for every command I would want to use. If the solution uses 'find',
it must do the equivalent of evaluating '{}/wildcardpattern' for those
commands that want a list of filenames, not just a directory name, even
though something like '{}/*' is unexpandable in 'find'.

The program uses the SysV function ftw(3c) and could be executed with the
command 'ftw startdirectory unixcommand commandparms', e.g. 'ftw /usr/include
grep pattern \*.h'.

#include <stdio.h>
#include <ftw.h>
#include <string.h>

char command[80];
int walk();

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

{
int ftwrtn,i;

	if (argc < 3) printf("USAGE: ftw path command\nargc=%d\n",argc);
	else {
	   strcpy(command,argv[2]);
	   for (i=3;i<argc;i++){
	      strcat(command," ");
	      strcat(command,argv[i]);
	   }
	   if((ftwrtn=ftw(argv[1],walk,60))==-1) perror("ftw(3c)");
	}
	exit(ftwrtn);
}

int walk(path,stat,num)
 
char *path;
int *stat,num;

{
char *cwd,*getcwd(),buf[100];

	if (num==FTW_D) {
	   if((cwd=getcwd(buf,100))==NULL) perror("getcwd(3c)");
	   if(chdir(path)==-1) perror("chdir(2)");
	   printf("****************************************\n");
	   printf("in %s do: %s\n",path,command);
	   printf("****************************************\n");
/* adapt the following line according to your system's syntax */
/*	   if(fflush(0)==-1) perror("fflush(3s)");*/
	   printf("\nSystem(3s) return value=%x\n\n\n",system(command));
	   if(chdir(cwd)==-1) perror("chdir(2)");
	}
	return(0);
}
-- 
BURNS,JIM
Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a
Internet: gt0178a@prism.gatech.edu

les@chinet.chi.il.us (Leslie Mikesell) (09/01/90)

In article <13204@hydra.gatech.EDU> gt0178a@prism.gatech.EDU (BURNS,JIM) writes:
>Listed below is a 'C' program I wrote because I got tired of 'ls -R' and
>'find' not understanding wildcards, even if quoted. Can anyone tell me how
>to do something like

>find . -type d -exec 'general command with wildcards and {}' \;

Unless there is some requirement to do a single directory at a time you
could use:

find . -type f -name 'wildcard' -print | xargs command

xargs reads stdin for newline-delimited filenames and bundles them in
groups to pass on the command line to one or more executions of "command".
This is typically used to avoid the "argument list too long" problem
when you let the shell expand wildcards on an unknown number of files. 

Of course if the list will never exceed the shell command line buffer
and you know how deep the directory tree goes, you can just use:

command * */* */*/* (etc..)

Les Mikesell
  les@chinet.chi.il.us

gt0178a@prism.gatech.EDU (BURNS,JIM) (09/02/90)

in article <1990Sep01.154949.16559@chinet.chi.il.us>, les@chinet.chi.il.us (Leslie Mikesell) says:
> Unless there is some requirement to do a single directory at a time you
> could use:
> 
> find . -type f -name 'wildcard' -print | xargs command

Yeah, I guess I was getting to hung up on the order. Thanx.

For those who are interested tho', I did play with it some more, and got
the script below to work the same way as the 'c' program, and it executes
in 1/2 to 3/4 the time (according to the ksh time command), and is 100th
the size and works on BSD - go figure!

-rwxr-xr-x  1 gt0178a       290 Sep  1 17:07 ftw*
-rwxr-xr-x  1 gt0178a     23949 Aug 27 20:16 ftw2*

startdir=$1;shift
for i in `du $startdir|awk '{print $2}'`;do
(cd $i
echo '****************************************'
echo -n "in $i do ";set -f;echo $*;set +f
echo '****************************************'
eval $*
return=$?
echo ""
echo Command return code = $return
echo "";echo "")
done
-- 
BURNS,JIM
Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a
Internet: gt0178a@prism.gatech.edu