On Apr 16, 2007, at 2:09 AM, Kevin Ballard wrote:

The users of the original find command was, well, nobody. The few times I considered using it, I shied away as well. Why? Because I didn't want to add dependencies on the API when it was, frankly, pretty bad. It set a global variable (yes, not even local to the calling procedure, but global) called _filename.

I'm not defending making the _filename var a fixed global - I even said in the previous threads on this topic that this was a clear and obvious shortcoming that needed fixing (which is also why I raised no complaint whatsoever about this aspect of the change).

I'm also confused as to your complaint about it executing the body every time. With your original implementation, it executed the match every time, and every time it succeeded (most of the time, as it defaulted to "expr 1") it would then execute the body (which defaulted to printing the file, though I'm not sure why as any practical usage of the command doesn't want to print the result).

The fact that { 1 } and { print $_filename } are the defaults shouldn't be taken as an indication that we don't need a flexible API.  You can type "find ." and get useful results at the shell, too, but no one argues that find(1)'s other options should be deprecated since that's all one would ever want to do with it.   I do a lot of things with find(1) that don't print the result - they manipulate the filenames found silently and move on.

I'm also hardly defending the original find API as perfect - never said it was.   However, like xinstall, I think it's a worthwhile goal to make it follow in the footsteps of its command-line analog so as to ease the process of people coming up to speed with it.   It's not going to be identical, naturally, since Tcl is a "real language" unlike /bin/sh and there are more powerful things you can do with it, but it should at least follow the POLA as much as it can.  I'm still waiting for some usage examples which demonstrate how this is a marked improvement.

In any case, the standard usage for something like this is to traverse a filesystem and perform some action on each file that matches the criteria. The new find command is intended specifically for this. It's basically a foreach on a recursive glob. A theoretical usage might look as follows:

find src file {
    switch -glob $file {
        .svn -
        CVS  { continue }
        *.o  { file delete $file }
    }
}

And maybe it's just me, but I would find this to be far more readable (and concise):

find file src {string match *.o $file} {file delete $file}

Note that I'm also talking about "general case" usage here, where the user is really trying to accomplish a simple and straight-forward job in one line without too much knowledge of the internals of find's recursion behavior, something I think you'll find to be true in the majority of usage scenarios rather than the converse.   Is that one line equivalent to your script?   No, because as you note, we don't short-circuit recursion in the .svn or CVS cases, but I also think your example is just a wee bit contrived given that most folks will be using this primitive to do operations in $destroot and not checked-out trees of source where this kind of short-circuit behavior is typical or even important.  Still, if you were to allow multiple expr/body pairs, I suppose you could always do it like this:

find file src {regex .svn|CVS $file} {return 1} {string match *.o $file} {file delete $file} 

Where "return 1" could have the special case meaning of "don't recurse."   Again, however, I don't see this as the typical usage case, just as people don't typically use find(1) with 11 predicates and parenthesized sub-expressions even though that's technically possible.  They use maybe one predicate and a fairly typical action, like -exec rm {} or print.   That's the usage case I was trying to optimize for in my version and while I don't think I necessarily did the best job, I think you've gotten further away, not closer, to the goal of making it really simple for the majority of intended usage scenarios.

- Jordan