Minimal Perl for Unix and Linux People | Page 2
Perl as a (Better) Find Command
6.1 Introducing Hybrid
In earlier chapters, we discussed Perl programs that served as more powerful replacements for grep, sed, and awk by exploiting the advanced capabilities of Perl's closely related facilities (e.g., the matching and substitution operators).
Although Perl has less intimate connections to most other Unix utilities, in many cases it can still be used to add value to,2 if not to completely replace, another utility. Accordingly, we'll approach our discussion of find differently than we did the discussions of grep, sed, and AWK. Specifically, we'll generally use Perl commands to perform additional filtering of find's output rather than to eliminate the use of find altogether. This approach allows us to take advantage of find's ability to generate filenames by recursively descending into directories, rather than having to duplicate that functionality in Perl.3
Our primary focus in this chapter will be on find | perl pipelines that serve as functional enhancements to find rather than replacements for find. In addition to this primary theme, we'll also consider possible improvements to grep and sed-like programs (covered in chapters 3 and 4), which can benefit from many of the enhanced file-finding services we'll be discussing.
We'll begin by comparing find's file-testing capabilities with Perl's.
6.2 File Testing Capabilities of find vs. Perl
Table 6.1 shows the syntax for Perl's file-test operators. 4 You have the option of supplying an explicit filename argument when conducting a file test, as in
Alternatively, you can omit the filename, causing the data variable (
$_) to be accessed as the implicit argument:
In addition, the result of a test can be complemented by preceding its associated operator with the "
!" character, as in the following reverse-logic variation on the previous example:
Table 6.2 lists a variety of attributes for file s and shows, for Perl and significant versions of find, which ones are impossible, possible, or easy to test. The table also shows, in its rightmost column, the Perl operator that's used to perform each file attribute test.
The most basic file attribute tests (shown in the top panel) are rated as easy to perform with both versions of find as well as Perl. On the other hand, the second panel shows that all permission-related tests that are easy with Perl are impossible to perform with find.
The table also shows that the text-file and binary-file tests provided by Perl (
-B) are impossible with find, and the three other tests in the third panel are easier with Perl.
For example, Perl's test for a file's "sticky bit" being set is
Âk filename, whereas find requires the more complicated
Âperm -01000. All it takes to bungle the latter test is the omission of the second "-" or the misplacement of the 1 relative to all those 0s, which is why Perl rates an E (for easy), but find a P (for possible) on this test.5
The bottom panel shows several tests that are easier with find than Perl, because you have to test for these attributes using the stat function (discussed in section 7.2.3) rather than a file-test operator.
All in all, Perl stacks up relatively well against find, especially when you consider that Perl makes certain extremely helpful tests possible, or even easy (viz., those in the second and third panels). For example, Perl' s unique offering of six read/write/execute tests solves a long-standing problem in Unix programming. Why? Because Perl (on Unix) actually interprets the permissions a file grants to its User (a.k.a. owner), Group, and Others in light of the Real/Effective UID and GID of the person running the testÂin the same way the Unix kernel doesÂand yields a True/False code to indicate whether the specified access would be permitted.
find only gives you the ability to determine if a particular user owns a file (e.g., -
usernigel) and whether it has particular permission bits set or not (e.g.,
-perm-0400). What's missing is the all-important logicÂprovided by PerlÂthat determines whether the current user will be granted a particular type of access to the file, according to the (rather involved) rules of Unix.
In short, Perl's permission tests report the implications of the file's ownerships and permissions on the current user's activities, whereas find merely provides isolated bits of information from which a programmer must draw her own conclusions.
Each tool has its strengths, so with these differences in mind, let's look at some ways to augment
find's capabilities with Perl.