ch11_06.htm
来自「by Randal L. Schwartz and Tom Phoenix I」· HTM 代码 · 共 924 行 · 第 1/3 页
HTM
924 行
</tr><tr><td><blockquote><pre class="code">-A</pre></blockquote></td><td><p>Access age (measured in days)</p></td></tr><tr><td><blockquote><pre class="code">-C</pre></blockquote></td><td><p>Inode-modification age (measured in days)</p></td></tr></table><p><p>The tests <tt class="literal">-r</tt>, <tt class="literal">-w</tt>,<tt class="literal">-x</tt>, and <tt class="literal">-o</tt> tell whether thegiven attribute is true for the effective user or group ID,<a href="#FOOTNOTE-266">[266]</a> which essentially refers to the person who is "incharge of" running the program.<a href="#FOOTNOTE-267">[267]</a> These tests look atthe "permission bits" on the file to see what ispermitted. If your system uses Access Control Lists (ACLs), the testswill use those as well. These tests generally tell whether the systemwould <em class="emphasis">try</em> to permit something, but itdoesn't mean that it really would be possible. For example,<tt class="literal">-w</tt> may be true for a file on a CD-ROM, even thoughyou can't write to it, or <tt class="literal">-x</tt> may be true onan empty file, which can't truly be executed.</p><blockquote class="footnote"><a name="FOOTNOTE-266" /><p>[266]The <tt class="literal">-o</tt> and <tt class="literal">-O</tt> testsrelate only to the user ID and not to the group ID.</p></blockquote><blockquote class="footnote"> <a name="FOOTNOTE-267" /><p>[267]Note foradvanced students: the corresponding <tt class="literal">-R</tt>,<tt class="literal">-W</tt>, <tt class="literal">-X</tt>, and<tt class="literal">-O</tt> tests use the real user or group ID, whichbecomes important if your program may be running set-ID; in thatcase, it's generally the ID of the person who requested runningit. See any good book about advanced Unix programming for adiscussion of set-ID programs.</p> </blockquote><p>The <tt class="literal">-s</tt> test does return true if the file isnonempty, but it's a special kind of true. It's thelength of the file, measured in bytes, which evaluates as true for anonzero number.</p><p>On a Unix filesystem,<a href="#FOOTNOTE-268">[268]</a> there arejust seven types of items, represented by the seven file tests<tt class="literal">-f</tt>, <tt class="literal">-d</tt>, <tt class="literal">-l</tt>,<tt class="literal">-S</tt>, <tt class="literal">-p</tt>, <tt class="literal">-b</tt>,and <tt class="literal">-c</tt>. Any item should be one of those. But ifyou have a <a name="INDEX-802" />symbolic link pointing to a file, thatwill report true for both <tt class="literal">-f</tt> and<tt class="literal">-l</tt>. So if you want to know whether something is asymbolic link, you should generally test that first. (We'lllearn more about symbolic links in <a href="ch13_01.htm">Chapter 13, "Manipulating Files and Directories"</a>.)</p><blockquote class="footnote"> <a name="FOOTNOTE-268" /><p>[268]This is the case on manynon-Unix filesystems, but not all of the file tests are meaningfuleverywhere. For example, you aren't likely to have blockspecial files on your non-Unix system.</p> </blockquote><p>The age tests, <tt class="literal">-M</tt>, <tt class="literal">-A</tt>, and<tt class="literal">-C</tt> (yes, they're uppercase), return thenumber of days since the file was last modified, accessed, or had itsinode changed.<a href="#FOOTNOTE-269">[269]</a> (The inode contains all of the information about the fileexcept for its contents -- see the <tt class="literal">stat</tt> systemcall manpage or a good book on Unix internals for details.) This agevalue is a full floating-point number, so you might get a value of<tt class="literal">2.00001</tt> if a file were modified two days and onesecond ago. (These "days" aren't necessarily thesame as a human would count; for example, if it's one thirty inthe morning when you check a file modified at about an hour beforemidnight, the value of <tt class="literal">-M</tt> for this file would bearound <tt class="literal">0.1</tt>, even though it was modified"yesterday.")</p><blockquote class="footnote"> <a name="FOOTNOTE-269" /><p>[269]This information will be somewhatdifferent on non-Unix systems, since not all keep track of the sametimes that Unix does. For example, on some systems, the ctime field(which the <tt class="literal">-C</tt> test looks at) is the file creationtime (which Unix doesn't keep track of), rather than the inodechange time; see the <em class="emphasis">perlport</em> manpage.</p></blockquote><p>When checking the age of a file, you might even get a negative valuelike <tt class="literal">-1.2</tt>, which means that the file'slast-access timestamp is set at about thirty hours in the future! Thezero point on this timescale is the moment your program startedrunning,<a href="#FOOTNOTE-270">[270]</a> so that value might meanthat a long-running program was looking at a file that had just beenaccessed. Or a timestamp could be set (accidentally or intentionally)to a time in the future.</p><blockquote class="footnote"> <a name="FOOTNOTE-270" /><p>[270]As recorded in the <tt class="literal">$^T</tt>variable, which you could update (with a statement like <tt class="literal">$^T= time;</tt>) if you needed to get the ages relative to adifferent starting time.</p> </blockquote><p>The tests <tt class="literal">-T</tt> and <tt class="literal">-B</tt> take a tryat telling whether a file is text or binary. But people who know alot about filesystems know that there's no bit (at least inUnix-like operating systems) to indicate that a file is a binary ortext file -- so how can Perl tell? The answer is that Perl cheats:it opens the file, looks at the first few thousand bytes, and makesan educated guess. If it sees a lot of null bytes, unusual controlcharacters, and bytes with the high bit set, then that looks like abinary file. If there's not much weird stuff then it looks liketext. As you might guess, it sometimes guesses wrong. If a text filehas a lot of Swedish or French words (which may have charactersrepresented with the high bit set, as some ISO-8859-somethingvariant, or perhaps even a Unicode version), it may fool Perl intodeclaring it binary. So it's not perfect, but if you just needto separate your source code from compiled files, or HTML files fromPNGs, these tests should do the trick.</p><p>You'd think that <tt class="literal">-T</tt> and<tt class="literal">-B</tt> would always disagree, since a text fileisn't a binary and vice versa, but there are two special caseswhere they're in complete agreement. If the file doesn'texist, both are false, since it's neither a text file nor abinary. Alternatively, if the file is empty, it's an empty textfile and an empty binary file at the same time, so they're bothtrue.</p><p>The <tt class="literal">-t</tt> file test returns true if the givenfilehandle is a TTY -- in short, if it's able to beinteractive because it's not a simple file or pipe. When<tt class="literal">-t STDIN</tt> returns true, it generally means that youcan interactively ask the user questions. If it's false, yourprogram is probably getting input from a file or pipe, rather than akeyboard.</p><p>Don't worry if you don't know what some of the other filetests mean -- if you've never heard of them, you won'tbe needing them. But if you're curious, get a good book aboutprogramming for <a name="INDEX-803" />Unix.(On non-Unix systems, these tests all try to give results analogousto what they do on Unix. Usually you'll be able to guesscorrectly what they'll do.)</p><p>If you omit the filename or filehandle parameter to a file test (thatis, if you have just <tt class="literal">-r</tt> or just<tt class="literal">-s</tt>, say), the default operand is the file named in<tt class="literal">$_</tt>.<a href="#FOOTNOTE-271">[271]</a> So, to test a list offilenames to see which ones are readable, you simply type:</p><blockquote class="footnote"> <a name="FOOTNOTE-271" /><p>[271]The <tt class="literal">-t</tt> filetest is an exception; since that test isn't useful withfilenames (they're never TTYs). By default it tests<tt class="literal">STDIN</tt>. </p> </blockquote><blockquote><pre class="code">foreach (@lots_of_filenames) { print "$_ is readable\n" if -r; # same as -r $_}</pre></blockquote><p>But if you omit the parameter, be careful that whatever follows thefile test doesn't look like it <em class="emphasis">could</em> be aparameter. For example, if you wanted to find out the size of a filein K rather than in bytes, you might be tempted to divide the resultof <tt class="literal">-s</tt> by <tt class="literal">1000</tt> (or<tt class="literal">1024</tt>), like this:</p><blockquote><pre class="code"># The filename is in $_my $size_in_K = -s / 1000; # Oops!</pre></blockquote><p>When the Perl parser sees the slash, it doesn't think aboutdivision; since it's looking for the optional operand for<tt class="literal">-s</tt>, it sees what looks like the start of a regularexpression in forward slashes. One simple way to prevent this kind ofconfusion is to put<a name="INDEX-804" />parentheses around the file test:</p><blockquote><pre class="code">my $size_in_k = (-s) / 1024; # Uses $_ by default</pre></blockquote><p>Of course, it's always safe to explicitly give a file test aparameter.</p><a name="lperl3-CHP-11-SECT-6.1" /><div class="sect2"><h3 class="sect2">11.6.1. The stat and lstat Functions</h3><p>While these file tests are fine for testing various attributesregarding a particular file or filehandle, they don't tell thewhole story. For example, there's no file test that returns thenumber of links to a<a name="INDEX-805" />file or the owner's<a name="INDEX-806" /><a name="INDEX-807" />user-ID (uid).To get at the remaining information about a file, merely call the<tt class="literal">stat</tt><a name="INDEX-808" /> function, which returns pretty mucheverything that the stat Unix system call returns (hopefully morethan you want to know).<a href="#FOOTNOTE-272">[272]</a></p><blockquote class="footnote"> <a name="FOOTNOTE-272" /><p>[272]On a non-Unix system, both<tt class="literal">stat</tt> and <tt class="literal">lstat</tt>, as well asthe file tests, should return "the closest thingavailable." For example, a system that doesn't have userIDs (that is, a system that has just one "user," in theUnix sense) might return zero for the user and group IDs, as if theone and only user is the system administrator. If<tt class="literal">stat</tt> or <tt class="literal">lstat</tt> fails, it willreturn an empty list. If the system call underlying a file test fails(or isn't available on the given system), that test willgenerally return <tt class="literal">undef</tt>. See the<em class="emphasis">perlport</em> manpage for the latest about what toexpect on different systems.</p> </blockquote><p>The operand to <tt class="literal">stat</tt> is a filehandle, or anexpression that evaluates to a filename. The return value is eitherthe empty list, indicating that the <tt class="literal">stat</tt> failed(usually because the file doesn't exist), or a 13-element listof numbers, most easily described using the following list of<a name="INDEX-809" />scalar variables:</p><blockquote><pre class="code">my($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($filename);</pre></blockquote><p>The names here refer to the parts of the stat structure, described indetail in the <em class="emphasis">stat(2)</em><a name="INDEX-810" /> manpage. You should probably look therefor the detailed descriptions. But in short, here's a quicksummary of the important ones:</p><dl><dt><b><tt class="literal">$dev</tt><a name="INDEX-811" /> and <tt class="literal">$ino</tt><a name="INDEX-812" /> </b></dt><dd>The device number and inode number of the file. Together they make upa "license plate" for the file. Even if it has more thanone name (hard link), the combination of device and inode numbersshould always be unique.</p></dd></dl><dl><dt><b><tt class="literal">$mode</tt><a name="INDEX-813" /></b></dt><dd>The set of permission bits for the file, and some other bits. Ifyou've ever used the Unix command <i class="command">ls -l</i> toget a detailed (long) file listing, you'll see that each lineof output starts with something like <tt class="literal">-rwxr-xr-x</tt>.The nine letters and hyphens of file permissions<a href="#FOOTNOTE-273">[273]</a> correspond to the nine least-significant bits of<tt class="literal">$mode</tt>, which would in this case give the octalnumber <tt class="literal">0755</tt>. The other bits, beyond the lowestnine, indicate other details about the file. So if you need to workwith the mode, you'll generally want to use the bitwiseoperators covered later in this chapter.</p><blockquote class="footnote"> <a name="FOOTNOTE-273" /><p>[273]Thefirst character in that string isn't a permission bit; itindicates the type of entry: a hyphen for an ordinary file,<tt class="literal">d</tt> for directory, or <tt class="literal">l</tt> forsymbolic link, among others. The <i class="command">ls </i>commanddetermines this from the other bits past the least-significant nine.</p> </blockquote></dd></dl><dl><dt><b><tt class="literal">$nlink</tt><a name="INDEX-814" /><a name="INDEX-815" /> </b></dt><dd>The number of (hard) links to the file or directory. This is thenumber of true names that the item has. This number is always<tt class="literal">2</tt> or more for directories and (usually)<tt class="literal">1</tt> for files. We'll see more about this whenwe talk about creating links to files in <a href="ch13_01.htm">Chapter 13, "Manipulating Files and Directories"</a>. In the listing from <i class="command">ls -l</i>,this is the number just after the permission-bits string.</p></dd></dl><dl><dt><b><tt class="literal">$uid</tt><a name="INDEX-816" /><a name="INDEX-817" /><a name="INDEX-818" /> and<a name="INDEX-819" /><a name="INDEX-820" /> <tt class="literal">$gid</tt></b></dt><dd>The numeric user-ID and group-ID showing the file's ownership.</p></dd></dl><dl><dt><b><tt class="literal">$size</tt><a name="INDEX-821" /><a name="INDEX-822" /></b></dt><dd>The size in bytes, as returned by the <tt class="literal">-s</tt> file test.</p></dd></dl><dl><dt><b><tt class="literal">$atime</tt><a name="INDEX-823" /><a name="INDEX-824" /><a name="INDEX-825" />, <tt class="literal">$mtime</tt>, and <tt class="literal">$ctime</tt> </b></dt><dd>The three
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?