Q: Exec'ing grep from Tcl? 
Author Message
 Q: Exec'ing grep from Tcl?

I've been trying to write a Tcl script to help me find references to various
strings in the code for a project I'm working on.  All the code is contained
in .c files in a handful of directories.  I have typically been cd'ing to
each directory and typing: grep  string  *.c from a csh prompt.  Since I've
been learning Tcl, I thought "Hey, I'll save myself a little time and
practice my Tcl skills by writing a little script to automate that!"  I
thought the following would do the trick:

#!/usr/bin/tclsh
# cgrep script - for 'code grep'

cd /mnt/Development2/CDS        ;# Change to project parent directory

set str [lindex $argv 0]                   ;# Store search string in str

foreach dir {Cabio  Data  Executive  Lib  Sound  Vibration}  {

   cd $dir
   puts [exec grep  $str  *.c]
   cd ..

Quote:
}

This results in the following:
Error: Cannot open *.c
No such file or directory . . .

Huh?  I played around with it and found that, from an interactive Tcl
prompt, I could enter "grep string *.c" and it would work as expected, but
the minute I entered "exec grep string *.c", the wildcard file pattern no
longer worked, resulting in the same "Cannot open *.c" error.

Could someone please explain this behavior to me, and tell me how I might
work around it?  I have a vague idea that I have to use 'glob' somehow, but
I haven't quite been able to work it out. . .

Thanks in advance,

Dave Wolfe
gForce Technologies, Inc.



Wed, 02 May 2001 03:00:00 GMT  
 Q: Exec'ing grep from Tcl?
Okay, I was able to get it to work, but it was tricky (mostly because I'm
new at Tcl, I hope).  I'm still very curious about why the other version
didn't work.  I feel like I *need* to understand, or I'll just keep screwing
things up.  (Tcl syntax seems *really* confusing to me right now!)

Would anyone care to comment on the code that follows?  It kinda seems
'cumbersome' to me, even though it works great and has already been quite
useful.  I'm particularly bothered by the error-check portion that checks to
see if matchPhrase is equal to "child process exited abnormally".  Maybe I'm
just too used to C, but it 'feels funny'.  Is this a standard way of doing
things?  Please let me know how I can make this code better:
----------------------------------------------------------------------------
---------------------------------------
#!/usr/tcl/tclsh

# This script recursively greps all '.c' and '.h' files in CDS and its
# subdirectories.  Use it to find all code references to a particular
string.
# USAGE:  grepcds "SearchString"

proc GrepIt { startDir strPat } {
   set pwd [pwd]
   if [catch {cd $startDir} err] {
      puts stderr $err
      return
   }

   foreach match [glob  -nocomplain  *.{c,h}]  {

      catch {exec grep $strPat $match} matchPhrase

      if {$matchPhrase != "child process exited abnormally"} {
         puts stdout "[file join $startDir $match]:\n$matchPhrase\n"
      }
   }

   foreach file [glob  -nocomplain  *] {
      if [file isdirectory $file] {
         GrepIt [file join $startDir $file] $strPat
      }
   }
   cd $pwd

Quote:
}

set str [lindex $argv 0]
set sdir "/mnt/Development2/CDS"

puts ""    ; # Print a blank line

GrepIt $sdir $str

----------------------------------------------------------------------------
-----------------------------------------

Thanks for any advice you can give. . .

Best regards,

Dave Wolfe
gForce Technologies Inc.

P.S.  I lifted most of this code right off of p. 107 of Brent Welch's book
and modified it just slightly,  so if it happens to look good, it's to his
credit! ;->



Wed, 02 May 2001 03:00:00 GMT  
 Q: Exec'ing grep from Tcl?

Quote:

>Okay, I was able to get it to work, but it was tricky (mostly because I'm
>new at Tcl, I hope).  I'm still very curious about why the other version
>didn't work.  I feel like I *need* to understand, or I'll just keep screwing
>things up.  (Tcl syntax seems *really* confusing to me right now!)

>Would anyone care to comment on the code that follows?  It kinda seems
>'cumbersome' to me, even though it works great and has already been quite
>useful.  I'm particularly bothered by the error-check portion that checks to
>see if matchPhrase is equal to "child process exited abnormally".  Maybe I'm
>just too used to C, but it 'feels funny'.  Is this a standard way of doing
>things?  Please let me know how I can make this code better:
>----------------------------------------------------------------------------
>---------------------------------------
>#!/usr/tcl/tclsh

># This script recursively greps all '.c' and '.h' files in CDS and its
># subdirectories.  Use it to find all code references to a particular
>string.
># USAGE:  grepcds "SearchString"

>proc GrepIt { startDir strPat } {
>   set pwd [pwd]
>   if [catch {cd $startDir} err] {
>      puts stderr $err
>      return
>   }

>   foreach match [glob  -nocomplain  *.{c,h}]  {

>      catch {exec grep $strPat $match} matchPhrase

>      if {$matchPhrase != "child process exited abnormally"} {
>         puts stdout "[file join $startDir $match]:\n$matchPhrase\n"
>      }
>   }

I'd write something more like

  if {![catch {exec grep $strPat $match} matchPhrase]} {
    puts "[file join $startDir $match]:\n$matchPhrase\n"
  }

Quote:

>   foreach file [glob  -nocomplain  *] {
>      if [file isdirectory $file] {
>         GrepIt [file join $startDir $file] $strPat
>      }
>   }
>   cd $pwd
>}

>set str [lindex $argv 0]
>set sdir "/mnt/Development2/CDS"

>puts ""    ; # Print a blank line

>GrepIt $sdir $str

                        .
                        .
                        .
The short answer to the question in your previous post is [glob].
A slightly longer answer appears in <URL:http://
starbase.neosoft.com/~claird/comp.lang.tcl/fmm.html#ls>.

There ought to be a standard find, but there isn't, yet.  I might
read more about this, later.

grep is funny.  I might add an entry to the FMM about it.
--

Cameron Laird           http://starbase.neosoft.com/~claird/home.html



Wed, 02 May 2001 03:00:00 GMT  
 Q: Exec'ing grep from Tcl?

Quote:

> #!/usr/tcl/tclsh

> # This script recursively greps all '.c' and '.h' files in CDS and its
> # subdirectories.  Use it to find all code references to a particular
> string.
> # USAGE:  grepcds "SearchString"

> proc GrepIt { startDir strPat } {
>    set pwd [pwd]
>    if [catch {cd $startDir} err] {
>       puts stderr $err
>       return
>    }

>    foreach match [glob  -nocomplain  *.{c,h}]  {

>       catch {exec grep $strPat $match} matchPhrase

>       if {$matchPhrase != "child process exited abnormally"} {
>          puts stdout "[file join $startDir $match]:\n$matchPhrase\n"
>       }
>    }

>    foreach file [glob  -nocomplain  *] {
>       if [file isdirectory $file] {
>          GrepIt [file join $startDir $file] $strPat
>       }
>    }
>    cd $pwd
> }

> set str [lindex $argv 0]
> set sdir "/mnt/Development2/CDS"

> puts ""    ; # Print a blank line

> GrepIt $sdir $str

OK, you got it!  But for this sort of task, surely the
ordinary shell is the tool of choice:

#!/bin/sh
startdir=/mnt/Development2/CDS
cd $startdir
for d in * ; do
   find $d -regex ".*\.\(c\|h\)" | xargs grep $1
done

--
Allin Cottrell
Department of Economics
Wake Forest University, NC



Thu, 03 May 2001 03:00:00 GMT  
 Q: Exec'ing grep from Tcl?

Yes! Thanks for that suggestion.  Why reinvent the wheel, right?  I'm not
very experienced at shell script programming in general, so I missed what
may be obvious to others.

I am amazed at the raw power of scripting languages for eliminating tedious,
repetitive tasks that aren't time-intensive.  Before starting to play around
with Tcl, I knew a little about sh, csh, bash, etc., but I didn't really
'get it'.  (I only recently started to develop in a Unix environment.)  I
thought shells were essentially just windows for launching other
applications.  Duh!  Hello?! Now I see that, with just a few lines of code,
I can create my *own* commands that integrate seamlessly with the rest of
the operating system.  No one will even know that they're not builtin
commands!  This is pretty exciting stuff. . .

Now I just need to learn how to write really tight scripts that accept
multiple command line arguments.  The syntax for *all* of these different
scripting languages seems pretty cryptic to me right now, but I can see it
is definitely worth it to slog through and get comfortable with the most
common ones. . .

-Dave

P.S.  Allin, maybe you could email me a csh script that changes the command
prompt to the hostname + the current directory?  (e.g. Zaphod:
/mnt/Development2/CDS # ).  I have seen this trick, and know that it has to
be implemented in .cshrc somewhere (probably as an alias for cd?), but I
can't quite get the syntax right. . . .



Fri, 04 May 2001 03:00:00 GMT  
 Q: Exec'ing grep from Tcl?

Quote:

> I am amazed at the raw power of scripting languages for eliminating tedious,
> repetitive tasks that aren't time-intensive.

Yes, shell scripting for fun and profit.

Quote:
> Now I just need to learn how to write really tight scripts that accept
> multiple command line arguments.  The syntax for *all* of these different
> scripting languages seems pretty cryptic to me right now, but I can see it
> is definitely worth it to slog through and get comfortable with the most
> common ones. . .

I've found that bash scripting is relatively easy to learn.
Learning
tcl is worthwhile, though: it comes into its own when you use wish
to pop up GUI stuff, which adds another dimension to the power of
scripting.

Quote:
> P.S.  Allin, maybe you could email me a csh script that changes the command
> prompt to the hostname + the current directory?

set prompt = "%m:%~%# "

(put in your .cshrc to make it happen automatically each time
you log on)

--
Allin Cottrell
Department of Economics
Wake Forest University, NC



Fri, 04 May 2001 03:00:00 GMT  
 Q: Exec'ing grep from Tcl?

Quote:

> Now I just need to learn how to write really tight scripts that accept
> multiple command line arguments.  

One solution to this sort of problem is:

    #!/bin/sh
    # restart using wish \

    package require opt 0.1

    ::tcl::OptProc main {
        {-foo "A flag"}
        {-bar -choice {fie fi fo fum}}
        args
    } {
        if {$foo} {
            puts "Foo"
        } else {
            switch -- $bar {
                fie -
                fi {
                    puts "Starts with \"fi\""
                }
                fo {
                    puts "fo what?"
                }
                fum {
                    puts "I smell the {*filter*} of an englishmun"
                }
            }
        }
        puts "other args:$args"
    }

    eval main $argv

OptProc comes with Tcl 8.0 but is not documented in the standard
distribution.  Check out the Scriptics update page for a copy of the man
page.  (Thanks to Larry Virden for pointing out that this use of OptProc
is non-obvious.  One of these days I need to revise the man page.)

                                       Chris
--
Rens-se-LEER is a county.  RENS-se-ler is a city.  R-P-I is a school!



Fri, 04 May 2001 03:00:00 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Tcl exec'ing imagemagick on Windows

2. Exec not exec-ing sh scripts in tcl 7.5b1

3. grep'ing with wildcards.

4. 'with'ing and 'use'ing

5. un-'upvar'ing/un-'global'ing variables

6. FTP'ing and FAX'ing from within C4b

7. exec'ing an import

8. Problem exec'ing a multithreaded program

9. Trivial question about exec'ing a shell script

10. exec'ing in background

11. exec'ing sql loader

12. exec'ing multiple wish windows on MacOSX

 

 
Powered by phpBB® Forum Software