tcs%usna.uucp@BRL-BMD.ARPA (09/25/84)
How do I build a pipe within the exec portion of find? Example: find /etc -name printcap -exec cat {} | lpr \; I've tried lots of combinations of escaped parens, exec'ing the shell, etc and nothing works. I have gotten this to work: find /tmp -name tobuy -exec junk1 {} \; junk1: cat $1 | more But I'd rather know how to do it without having another file lying around. If it can be done, please explain the combination of escapes, etc you use make it work. Thanks. -tcs Terry Slattery U.S. Naval Academy 301-267-4413 ARPA: tcs@brl-bmd UUCP: decvax!brl-bmd!usna!tcs
rpw3@redwood.UUCP (Rob Warnock) (09/27/84)
[ Wizards, be patient. This IS net.unix, ne? ] +--------------- | How do I build a pipe within the exec portion of find? Example: | find /etc -name printcap -exec cat {} | lpr \; | I've tried lots of combinations of escaped parens, exec'ing | the shell, etc and nothing works... | Terry Slattery U.S. Naval Academy 301-267-4413 +--------------- I have never gotten it to work either (except like your "junk" auxiliary shell script), but the following neat/ugly/cute/hacky method sprang to mind one day as I was reading Kernighan & Pike [pp 86-87ff, see also "pick"]: $ for i in `find . <pattern> -print` > do echo $i # so we can see what we're doing > cat -v $i | lpr # ...or anything you want at all... > done For C-shell users, that's: % foreach i (`find . <pattern> -print`) ? echo $i # so we can see what we're doing ? cat -v $i | lpr ? end This lets you do more than one thing to the file, as well. Normally, the "{}" token can be used exactly once, so things like "mv {} {}-" don't work. Here, you can play games like "mv $i olddir/`basename $i`.old", and such. K & P also show an example of using "grep" to select files by their contents. Since this is USENET, I will make it news-oriented (let $SN be your spool dir): $ for i in `grep -l '^Subj.*[aA]pple.*[sS]haft' \`find $SN/net/micro -print\`` > do echo $i > pr -h Apple-Shaft-Articles $i | lpr > done This will print each article in "net.micro.all" that contains "Apple...Shaft" in the subject line, as in a recent set of postings. (Surprise! The upgrade controversy raged across several groups!) [I tried this. It worked. However, I had just done a severe "expire". So,...] WARNING: Make sure that the "find" is not going to give you so much stuff that your shell (or your system) blows up from an over-large argument list. (That is, DON'T do "for i in `find / -print`") An example of practical uses includes going through the news spool area fixing up ownership, group, and modes of any directories that created by "root" or "uucp" instead of "news" (seems to occasionally happen): $ for i in `find /usr/spool/news ! -user news -print` > do ls -adl $i # show the culprit > /etc/chown news $i > /etc/chgrp news $i # for those who don't have chowngrp > chmod 755 $i # or whatever protection you run with > done I'm sure you can think of lots of uses. WARNING#2: If the command string gets so long (more than 2-3 lines) that your error rate typing it wipes out the savings you got from using "immediate mode", go back and edit a real shell script to do the work, test it on a couple of files, then feed it to a "find ... -exec <script> \;". It's safer. Rob Warnock UUCP: {ihnp4,ucbvax!amd}!fortune!redwood!rpw3 DDD: (415)369-7437 Envoy: rob.warnock/kingfisher USPS: Suite 203, 4012 Farm Hill Blvd, Redwood City, CA 94061
merlyn@sequent.UUCP (09/28/84)
#endif BUG rpw3@redwood.UUCP sez: >> WARNING: Make sure that the "find" is not going to give you so much stuff >> that your shell (or your system) blows up from an over-large argument list. >> (That is, DON'T do "for i in `find / -print`") A way around this is to do something like: find <dirs> <selection> -print | while read i do <$i commands> done Works real slick. Example: find / -size 0 -print | while read i do ls -ldg $i done does an ls on all zero-length files on the system. -- A particularly personal and original observation from the thought-stream of Randal L. ("your favorite phrase here") Schwartz, esq. (merlyn@sequent.UUCP) (Former Official Legendary Sorcerer of the 1984 Summer Olympics) Sequent Computer Systems, Inc. (503)626-5700 (sequent = 1/quosine) UUCP: {decwrl,ogcvax,pur-ee,rocks34,shell,unisoft,vax135,verdix}!sequent!merlyn
fair@dual.UUCP (Erik E. Fair) (10/02/84)
>> From: tcs%usna.uucp@BRL-BMD.ARPA >> Newsgroups: net.unix >> Subject: creating pipes in find(1) >> Date: Tue, 25-Sep-84 11:51:16 PDT >> >> How do I build a pipe within the exec portion of find? >> Example: >> find /etc -name printcap -exec cat {} | lpr \; >> >> I've tried lots of combinations of escaped parens, exec'ing >> the shell, etc and nothing works. >> I have gotten this to work: >> find /tmp -name tobuy -exec junk1 {} \; >> >> junk1: >> cat $1 | more >> >> But I'd rather know how to do it without having another file >> lying around. >> >> If it can be done, please explain the combination of >> escapes, etc you use make it work. Thanks. >> -tcs >> Terry Slattery U.S. Naval Academy 301-267-4413 >> ARPA: tcs@brl-bmd UUCP: decvax!brl-bmd!usna!tcs I think what you want is something like this: find / -perm -4000 -exec ls -ls {} \; | Mail -s "Daily SUID Program Report" root Note the escaped semi-colon? That's part of the argument list to find(1). That's what terminates an exec list. Since the semi-colon is escaped, the shell (whichever one you use) will not use it to terminate the command. Clear? Erik E. Fair ucbvax!fair fair@ucb-arpa.ARPA dual!fair@BERKELEY.ARPA {ihnp4,ucbvax,hplabs,decwrl,cbosgd,sun,nsc,apple,pyramid}!dual!fair Dual Systems Corporation, Berkeley, California
fcy@iham1.UUCP (Fred Yankowski) (10/03/84)
In UNIX System V Release 1, 'find' processes its '-exec' arguments with 'execvp(II)', not 'system(III)'. This means that *no* shell processing is done: '|', '&', ';', '(', etc. are not interpreted by the shell. The command find / -type f -exec cat {} \| lpr \; will then execute cat "file" "|" "lpr" for each file "file" found by 'find' (got that?). That is, 'cat' is executed with three arguments: "file", "|", and "lpr". One handy idiom for processing files found by 'find' is: find dir <find arguments> -print | xargs <process> For example: find / -type f -print | xargs -n1 lpr does what seems to be desired in the first (faulty) 'find' command above. Even better is find / -type f -print | xargs lpr in which 'xargs' repeatedly gathers as many file names as fit in an internal buffer and executes 'lpr' against each such list of file arguments. The improvement is in execution time, since 'lpr' is fork/execed once for each list of files, rather than for each file alone. Similarly, cleaning out a directory is better accomplished with find . -type f -print | xargs rm rather than find . -type f -exec rm {} \; Fred Yankowski ::: AT&T Bell Laboratories ::: ihnp4!iham1!fcy IH 6B-216 x6902
johnl@cca.UUCP (10/04/84)
#R:sri-arpa:-1237800:ima:19700001:000:496 ima!johnl Oct 3 10:25:00 1984 > How do I build a pipe within the exec portion of find? > Example: > find /etc -name printcap -exec cat {} | lpr \; The short answer is that you can't -- find uses an exec() call to run what it runs, and exec won't create pipes. Any "|" characters are handled by the shell. In the Bourne shell, though, you can do stuff like this: find /etc -name foo - print | while read fn do cat $fn | lpr done I suppose that there's some way to do that in the C shell, too. John Levine, ima!johnl