Processing All Files in a Directory Recursively - Perl Cookbook [Book]
To ignore a whole directory tree, use -prune rather than checking every file in the tree. For example, to skip the directory `src/emacs' and all files. process_files() with the base path as 'path' process_files(): get a list of all files in . Perl , no longer use recursion (in the truest sense of the term) in order to. This script takes two (optional) arguments, the directory to partition, and the parition size. done in perl, ruby, or python. find with maxdepth 1 does only the directory; you #LIST="ls" #move everything #be careful, $folder will get moved also . How can I fix my relationship with my 7 month old cat after I've.
If the thing we see is not in Hook:: LexWrap, but comes directly after something that is, we replace its subroutine name with the one from the cache. LexWrap package, but in all other ways behaves the same as the original caller. Most of the wrap routine is actually just about argument checking, context propagation, and return value handling; we can slim it down to the following for our purposes: We might have been either handed a typeglob the tricky case or the name of a subroutine as a string.
If we have a string, the code looks like this: The second line turns the string into a subroutine reference using the glob reference syntax. The value will be available to the subroutine either as a simple scalar or in the latter two cases as a reference to the typeglob.
We know where it should go in the symbol table, and so we redefine the original subroutine with our new one. So this relatively complex module relies purely on two tricks that we have already examined: When the perl interpreter is handed some code, it translates it into an internal code, similar to other bytecode-compiled languages such as Java.
For instance, from the very short subroutine: Bytecode tree The B module provides functions that expose the nodes of this tree as objects in Perl itself. You can examine—and in some cases modify—the parsed representation of a running program. There are several obvious applications for this. For instance, if you can serialize the data in the tree to disk, and find a way to load it up again, you can store a Perl program as bytecode.
Bytecode and ByteLoader modules do just this. Those thinking that they can use this to distribute Perl code in an obfuscated binary format need to read on to our second application: Deparse module does this, and it can tell us a lot about how Perl understands different code: To understand how these modules do their work, you need to know a little about the Perl virtual machine.
Many of these operations will involve putting values on or taking them off a stack; unlike a real CPU, which uses registers to store intermediate results, most software CPUs use a stack model. Perl code enters the perl interpreter, gets translated into the syntax tree structure we saw before, and is optimized.
Part of the optimization process involves determining a route through the tree by joining the ops together in a linked list. In Figurethe route is shown as a dotted line. Optimized bytecode tree Each node on the tree represents an operation to be done: There are several different kinds of operators, classified by how they manipulate the stack.
For instance, there are the binary operators—such as add—which take two values off the stack and return a new value. List operators like print take a number of values off the stack, and the nullary pushmark operator is responsible for putting a special mark value on the stack to tell print where to stop.
The B module represents all these different kinds of operators as subclasses of the B:: OP class, and these classes contain methods allowing us to get the next module in the execution order, the children of an operator, and so on.
Similar classes exist to represent Perl scalar, array, hash, filehandle, and other values. We can convert any reference to a B:: CV object This B:: CV object represents the subroutine reference that Perl can, for instance, store in the symbol table.
Perl Cookbook by Nathan Torkington, Tom Christiansen
Depending on which op we have, there are two ways to navigate the op tree. To walk the tree in execution order, you can just follow the chain of next pointers: COP and the underlying C equivalent, COP; the name method returns the human-readable name of the operation, and desc gives its description as it would appear in an error message.
NULL, because the next pointer of the final op will be a C null pointer, which B handily converts to a Perl object with no methods. If you want to examine the tree in top-down order, something that is useful for creating things like B:: Deparse or altering the generated bytecode tree with tricks like optimizer and B:: Generate, then the easiest way is to use the B:: This allows you to set a callback and visit every op in a tree: Working with Perl at the op level requires a great deal of practice and knowledge of the Perl internals, but can lead to extremely useful tools like Devel:: Cover, an op-level profiler and coverage analysis tool.
Checking isa relationships is one way to ensure that an object will respond correctly to the methods that you want to call on it, but it is not necessarily the best one.
Another idea, that of duck typing, states that you should determine whether or not to deal with an object based on the methods it claims to respond to, rather than its inheritance. If our Tea class did not derive from Beverage:: Hot, but still had temperature, milk, and sugar accessors and brew and drink methods, we could treat it as if it were a Beverage:: In short, if it walks like a duck and it quacks like a duck, we can treat it like a duck. For instance, looking back at our B:: Instead of checking whether or not we have an instance of the appropriate classes, we can write generically applicable code by checking whether the object responds to the last method: This is used internally by Perl when you say: Suddenly, every object and every class name and remember that in Perl a class name is just a string responds to your new method.
However, if you say: Module in the current directory and probably fail. This makes it awkward to require modules by name programatically. You have to end up doing something like: Now you can say: And if it would not respond to a method before, then any call to it would have been a fatal error. We could use this to turn all unknown methods into accessors and mutators: Ruby is the creation of Japanese programmer Yukihiro Matsumoto, based on Perl and several other dynamic languages. One of these ideas is the singleton method, a method that only applies to one particular object and not to the entire class.
In Perl, the concept would look something like this: Now that we have an idea of what we want to achieve, half the battle is over. This is easy, since ref tells us directly. Next we have to make up a new class—a new package name for our singleton methods to live in. This has to be specific to the object, so we use the closest thing to a unique identifier for objects that Perl has: However, it should be a familiar concept.
If you treat an object as an ordinary string, you get the output we have just described. However, if you treat it as a number, you just get the 0x Unexpected Code The final set of advanced techniques in this chapter covers anything where Perl code runs at a time that might not be obvious: Some of the most striking effects in Perl can be obtained by arranging for code to be run at unexpected moments, but this must be tempered with care. On the other hand, these are powerful techniques.
The problem with such overloading is that it can quickly get wildly out of hand. Ruby, on the other hand, overloads the same operator on arrays to mean push. If we make flagrant use of overloading in Perl, we end up having to look at least twice at code like: Now, how do we do it? Simple operator overloading The classic example of operator overloading is a module that represents time. Seconds, from the Time:: Piece distribution does just this.
Seconds is that, as well as merely representing a number of seconds, you can convert between different units of duration: These objects definitely represent a number—a number of seconds. And that is precisely what happens: It tells Perl to look more carefully at operations involving objects of that class, and it registers methods for the given operators in a look-up table.
When an object is involved in an overloaded operation, the operation is looked up in the table and the resulting method called. Seconds objects are turned into numbers by having the seconds method called on them, ordinary numbers are passed through, and any other kind of object causes a fatal error.
Recursion (computer science)
Then the arguments are reordered to the original order. Once we have two ordinary numbers, we can add them together and return a new Time:: Seconds object based on the sum.
Finally, to avoid having to write such subroutines for every kind of operator, Time:: Seconds uses a feature of overload called fallback. This instructs Perl to attempt to automatically generate reasonable methods from the ones specified: Seconds sets fallback to undef, which means that Perl will try to use an autogenerated method but will die if it cannot find one.
In other words, it will always produce some value, somehow. This means that no automatic method generation will be tried, and any attempts to use the object with one of the operations you have not overloaded will cause a fatal error.
However, as well as performing arithmetic operations on Time:: How does it do that? The two most useful of these we have just seen with Time:: Like the node for linked lists, it is defined in terms of itself, recursively. There are two self-referential pointers: Note that because there are two self-referencing pointers left and righttree operations may require two recursive calls: A Binary search tree is a special case of the binary tree where the data elements of each node are in order.
Stupid gcc trick #2: finding all included files, recursively | Coding on the edges
Filesystem traversal[ edit ] Since the number of files in a filesystem may vary, recursion is the only practical way to traverse and thus enumerate its contents. Traversing a filesystem is very similar to that of tree traversaltherefore the concepts behind tree traversal are applicable to traversing a filesystem. More specifically, the code below would be an example of a preorder traversal of a filesystem.
It is, essentially, a recursive implementation, which is the best way to traverse a filesystem. It is also an example of direct and indirect recursion. The method "rtraverse" is purely a direct example; the method "traverse" is the indirect, which calls "rtraverse". This example needs no "base case" scenario due to the fact that there will always be some fixed number of files or directories in a given filesystem.
Implementation issues[ edit ] In actual implementation, rather than a pure recursive function single check for base case, otherwise recursive stepa number of modifications may be made, for purposes of clarity or efficiency.
Wrapper function at top Short-circuiting the base case, aka "Arm's-length recursion" at bottom Hybrid algorithm at bottom — switching to a different algorithm once data is small enough On the basis of elegance, wrapper functions are generally approved, while short-circuiting the base case is frowned upon, particularly in academia. Hybrid algorithms are often used for efficiency, to reduce the overhead of recursion in small cases, and arm's-length recursion is a special case of this.
Wrapper function[ edit ] A wrapper function is a function that is directly called but does not recurse itself, instead calling a separate auxiliary function which actually does the recursion. Wrapper functions can be used to validate parameters so the recursive function can skip theseperform initialization allocate memory, initialize variablesparticularly for auxiliary variables such as "level of recursion" or partial computations for memoizationand handle exceptions and errors.
In languages that support nested functionsthe auxiliary function can be nested inside the wrapper function and use a shared scope.