📄 ch09_01.htm
字号:
<HTML><HEAD><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen & Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly & Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:39:01Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="index.htm"TITLE="Perl Cookbook"><LINKREL="prev"HREF="ch08_21.htm"TITLE="8.20. Program: laston"><LINKREL="next"HREF="ch09_02.htm"TITLE="9.1. Getting and Setting Timestamps"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch08_21.htm"TITLE="8.20. Program: laston"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 8.20. Program: laston"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch09_02.htm"TITLE="9.1. Getting and Setting Timestamps"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 9.1. Getting and Setting Timestamps"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="chapter"><H1CLASS="chapter"><ACLASS="title"NAME="ch09-17883">9. Directories</A></H1><DIVCLASS="htmltoc"><P><B>Contents:</B><BR><ACLASS="sect1"HREF="#ch09-27257"TITLE="9.0. Introduction">Introduction</A><BR><ACLASS="sect1"HREF="ch09_02.htm"TITLE="9.1. Getting and Setting Timestamps">Getting and Setting Timestamps</A><BR><ACLASS="sect1"HREF="ch09_03.htm"TITLE="9.2. Deleting a File">Deleting a File</A><BR><ACLASS="sect1"HREF="ch09_04.htm"TITLE="9.3. Copying or Moving a File">Copying or Moving a File</A><BR><ACLASS="sect1"HREF="ch09_05.htm"TITLE="9.4. Recognizing Two Names for the Same File">Recognizing Two Names for the Same File</A><BR><ACLASS="sect1"HREF="ch09_06.htm"TITLE="9.5. Processing All Files in a Directory">Processing All Files in a Directory</A><BR><ACLASS="sect1"HREF="ch09_07.htm"TITLE="9.6. Globbing, or Getting a List of Filenames Matching a Pattern">Globbing, or Getting a List of Filenames Matching a Pattern</A><BR><ACLASS="sect1"HREF="ch09_08.htm"TITLE="9.7. Processing All Files in a Directory Recursively">Processing All Files in a Directory Recursively</A><BR><ACLASS="sect1"HREF="ch09_09.htm"TITLE="9.8. Removing a Directory and Its Contents">Removing a Directory and Its Contents</A><BR><ACLASS="sect1"HREF="ch09_10.htm"TITLE="9.9. Renaming Files">Renaming Files</A><BR><ACLASS="sect1"HREF="ch09_11.htm"TITLE="9.10. Splitting a Filename into Its Component Parts">Splitting a Filename into Its Component Parts</A><BR><ACLASS="sect1"HREF="ch09_12.htm"TITLE="9.11. Program: symirror">Program: symirror</A><BR><ACLASS="sect1"HREF="ch09_13.htm"TITLE="9.12. Program: lst">Program: lst</A></P><P></P></DIV><DIVCLASS="epigraph"ALIGN="right"><PCLASS="para"ALIGN="right"><I>Unix has its weak points but its file system is not one of them.</I></P><PCLASS="attribution"ALIGN="right">- Chris Torek </P></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch09-27257">9.0. Introduction</A></H2><PCLASS="para">To fully understand <ACLASS="indexterm"NAME="ch09-idx-1000004336-0"></A><ACLASS="indexterm"NAME="ch09-idx-1000004336-1"></A><ACLASS="indexterm"NAME="ch09-idx-1000004336-2"></A>directories, you need to be acquainted with the underlying mechanics. The following explanation is slanted towards the Unix filesystem, for whose system calls and behavior Perl's directory access routines were designed, but it is applicable to some degree to most other platforms.</P><PCLASS="para">A <ACLASS="indexterm"NAME="ch09-idx-1000005024-0"></A>filesystem consists of two parts: a set of data blocks where the contents of files and directories are kept, and an index to those blocks. Each entity in the filesystem has an entry in the index, be it a plain file, a directory, a link, or a special file like those in <CODECLASS="literal">/dev</CODE>. Each entry in the index is called an <EMCLASS="emphasis">inode</EM><ACLASS="indexterm"NAME="ch09-idx-1000005026-0"></A> (short for <EMCLASS="emphasis">index node</EM>). Since the index is a flat index, inodes are addressed by number.</P><PCLASS="para">A directory is a specially formatted file, whose inode entry marks it as a directory. A directory's data blocks contain a set of pairs. Each pair consists of the name of something in that directory and the inode number of that thing. The data blocks for <EMCLASS="emphasis">/usr/bin</EM> might contain:</P><TABLECLASS="informaltable"BORDER="1"CELLPADDING="3"><THEADCLASS="thead"><TRCLASS="row"VALIGN="TOP"><THCLASS="entry"ALIGN="LEFT"ROWSPAN="1"COLSPAN="1"><PCLASS="para">Name</P></TH><THCLASS="entry"ALIGN="LEFT"ROWSPAN="1"COLSPAN="1"><PCLASS="para">Inode</P></TH></TR></THEAD><TBODYCLASS="tbody"><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">bc</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><CODECLASS="literal">17</CODE></P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">du</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><CODECLASS="literal">29</CODE></P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">nvi</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><CODECLASS="literal"> 8</CODE></P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">pine</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><CODECLASS="literal">55</CODE></P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><EMCLASS="emphasis">vi</EM></P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para"><CODECLASS="literal"> 8</CODE></P></TD></TR></TBODY></TABLE><PCLASS="para">Every directory is like this, even the <ACLASS="indexterm"NAME="ch09-idx-1000005230-0"></A><ACLASS="indexterm"NAME="ch09-idx-1000005230-1"></A>root directory ( <EMCLASS="emphasis">/ </EM>). To read the file <EMCLASS="emphasis">/usr/bin/vi</EM>, the operating system reads the inode for <EMCLASS="emphasis">/</EM>, reads its data blocks to find the entry for <EMCLASS="emphasis">/usr</EM>, reads <EMCLASS="emphasis">/usr </EM>'s inode, reads its data block to find <EMCLASS="emphasis">/usr/bin</EM>, reads <EMCLASS="emphasis">/usr/bin</EM>'s inode, reads its data block to find <EMCLASS="emphasis">/usr/bin/vi</EM>, reads <EMCLASS="emphasis">/usr/bin/vi </EM>'s inode, and then reads the data from its data block.</P><PCLASS="para">The name in a directory entry isn't fully qualified. The file <EMCLASS="emphasis">/usr/bin/vi</EM> has an entry with the name <EMCLASS="emphasis">vi</EM> in the <EMCLASS="emphasis">/usr/bin</EM> directory. If you open the directory <EMCLASS="emphasis">/usr/bin</EM> and read entries one by one, you get filenames like <EMCLASS="emphasis">patch</EM>, <EMCLASS="emphasis">rlogin</EM>, and <EMCLASS="emphasis">vi</EM> instead of fully qualified names like <EMCLASS="emphasis">/usr/bin/patch</EM>, <EMCLASS="emphasis">/usr/bin/rlogin</EM>, and <EMCLASS="emphasis">/usr/bin/vi</EM>.</P><PCLASS="para">The inode has more than a pointer to the data blocks. Each inode also contains the type of thing it represents (directory, plain file, etc.), the size of the thing, a set of permissions bits, owner and group information, the time the thing was last modified, the number of directory entries that point to this inode, and so on.</P><PCLASS="para">Some operations on files change the contents of the file's data blocks; some change just the inode. For instance, appending to or truncating a file updates its inode by changing the size field. Other operations change the directory entry that points to the file's inode. Changing a file's name changes only the directory entry; it updates neither the file's data nor its inode.</P><PCLASS="para">Three fields in the inode structure contain the last access, change, and modification times: <CODECLASS="literal">atime</CODE><ACLASS="indexterm"NAME="ch09-idx-1000004341-0"></A><ACLASS="indexterm"NAME="ch09-idx-1000004341-1"></A><ACLASS="indexterm"NAME="ch09-idx-1000004341-2"></A><ACLASS="indexterm"NAME="ch09-idx-1000004341-3"></A>, <CODECLASS="literal">ctime</CODE>, and <CODECLASS="literal">mtime</CODE>. The <CODECLASS="literal">atime</CODE> field is updated each time the pointer to the file's data blocks is followed and the file's data is read. The <CODECLASS="literal">mtime</CODE> field is updated each time the file's data changes. The <CODECLASS="literal">ctime</CODE> field is updated each time the file's inode changes. The <CODECLASS="literal">ctime</CODE> is <EMCLASS="emphasis">not</EM> creation time; there is no way under standard Unix to find a file's <ACLASS="indexterm"NAME="ch09-idx-1000005016-0"></A>creation time.</P><PCLASS="para">Reading a file changes its <CODECLASS="literal">atime</CODE> only. Changing a file's name doesn't change <CODECLASS="literal">atime</CODE>, <CODECLASS="literal">ctime</CODE>, or <CODECLASS="literal">mtime</CODE> because it was only the directory entry that changed (it does change the <CODECLASS="literal">atime</CODE> and <CODECLASS="literal">mtime</CODE> of the directory the file is in, though). Truncating a file doesn't change its <CODECLASS="literal">atime</CODE> (because we haven't read, we've just changed the size field in its directory entry), but it does change its <CODECLASS="literal">ctime</CODE> because we changed its size field and its <CODECLASS="literal">mtime</CODE> because we changed its contents (even though we didn't follow the pointer to do so).</P><PCLASS="para">We can access a file or directory's inode by calling the built-in function <CODECLASS="literal">stat</CODE><ACLASS="indexterm"NAME="ch09-idx-1000004342-0"></A> on its name. For instance, to get the inode for <EMCLASS="emphasis">/usr/bin/vi</EM>, say:</P><PRECLASS="programlisting">@entry = stat("/usr/bin/vi") or die "Couldn't stat /usr/bin/vi : $!";</PRE><PCLASS="para">To get the inode for the directory <EMCLASS="emphasis">/usr/bin</EM>, say:</P><PRECLASS="programlisting">@entry = stat("/usr/bin") or die "Couldn't stat /usr/bin : $!";</PRE><PCLASS="para">You can stat filehandles, too:</P><PRECLASS="programlisting">@entry = stat(INFILE) or die "Couldn't stat INFILE : $!";</PRE><PCLASS="para">The <CODECLASS="literal">stat</CODE> function returns a list of the values of the fields in the directory entry. If it couldn't get this information (for instance, if the file doesn't exist), it returns an empty list. It's this empty list we test for with the <CODECLASS="literal">or</CODE> <CODECLASS="literal">die</CODE> construct. Be careful of using <CODECLASS="literal">||</CODE> <CODECLASS="literal">die</CODE> because that throws the expression into scalar context, in which case <CODECLASS="literal">stat</CODE> only reports whether it worked. It doesn't return the list of values. The <CODECLASS="literal">_</CODE><ACLASS="indexterm"NAME="ch09-idx-1000006158-0"></A><ACLASS="indexterm"NAME="ch09-idx-1000006156-0"></A> cache referred to below will still be updated, though.</P><PCLASS="para">The values returned by <CODECLASS="literal">stat</CODE> are listed in the following table.</P><TABLECLASS="informaltable"BORDER="1"CELLPADDING="3"><THEADCLASS="thead"><TRCLASS="row"VALIGN="TOP"><THCLASS="entry"ALIGN="LEFT"ROWSPAN="1"COLSPAN="1"><PCLASS="para">Element</P></TH><THCLASS="entry"ALIGN="LEFT"ROWSPAN="1"COLSPAN="1"><PCLASS="para">Abbreviation</P></TH><THCLASS="entry"ALIGN="LEFT"ROWSPAN="1"COLSPAN="1"><PCLASS="para">Description</P></TH></TR></THEAD><TBODYCLASS="tbody"><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">0</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">dev</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">Device number of filesystem</P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">1</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">ino</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">Inode number (the "pointer" field)</P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">2</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">mode</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">File mode (type and permissions)</P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">3</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">nlink</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">Number of (hard) links to the file</P></TD></TR><TRCLASS="row"VALIGN="TOP"><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">4</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">uid</P></TD><TDCLASS="entry"ROWSPAN="1"COLSPAN="1"><PCLASS="para">Numeric user ID of file's owner</P></TD></TR><TRCLASS="row"VALIGN="TOP"><TD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -