📄 perlopentut.1
字号:
.Ve.PPTo open a file for update, where that file must not already exist:.PP.Vb 1\& sysopen(FH, $path, O_RDWR | O_EXCL | O_CREAT);.Ve.PPTo open a file without blocking, creating one if necessary:.PP.Vb 1\& sysopen(FH, $path, O_WRONLY | O_NONBLOCK | O_CREAT);.Ve.Sh "Permissions a\*` la mode".IX Subsection "Permissions a` la mode"If you omit the \s-1MASK\s0 argument to \f(CW\*(C`sysopen\*(C'\fR, Perl uses the octal value0666. The normal \s-1MASK\s0 to use for executables and directories shouldbe 0777, and for anything else, 0666..PPWhy so permissive? Well, it isn't really. The \s-1MASK\s0 will be modifiedby your process's current \f(CW\*(C`umask\*(C'\fR. A umask is a number representing\&\fIdisabled\fR permissions bits; that is, bits that will not be turned onin the created files' permissions field..PPFor example, if your \f(CW\*(C`umask\*(C'\fR were 027, then the 020 part woulddisable the group from writing, and the 007 part would disable othersfrom reading, writing, or executing. Under these conditions, passing\&\f(CW\*(C`sysopen\*(C'\fR 0666 would create a file with mode 0640, since \f(CW\*(C`0666 & ~027\*(C'\fRis 0640..PPYou should seldom use the \s-1MASK\s0 argument to \f(CW\*(C`sysopen()\*(C'\fR. That takesaway the user's freedom to choose what permission new files will have.Denying choice is almost always a bad thing. One exception would be forcases where sensitive or private data is being stored, such as with mailfolders, cookie files, and internal temporary files..SH "Obscure Open Tricks".IX Header "Obscure Open Tricks".Sh "Re-Opening Files (dups)".IX Subsection "Re-Opening Files (dups)"Sometimes you already have a filehandle open, and want to make anotherhandle that's a duplicate of the first one. In the shell, we place anampersand in front of a file descriptor number when doing redirections.For example, \f(CW\*(C`2>&1\*(C'\fR makes descriptor 2 (that's \s-1STDERR\s0 in Perl)be redirected into descriptor 1 (which is usually Perl's \s-1STDOUT\s0).The same is essentially true in Perl: a filename that begins with anampersand is treated instead as a file descriptor if a number, or as afilehandle if a string..PP.Vb 2\& open(SAVEOUT, ">&SAVEERR") || die "couldn\*(Aqt dup SAVEERR: $!";\& open(MHCONTEXT, "<&4") || die "couldn\*(Aqt dup fd4: $!";.Ve.PPThat means that if a function is expecting a filename, but you don'twant to give it a filename because you already have the file open, youcan just pass the filehandle with a leading ampersand. It's best touse a fully qualified handle though, just in case the function happensto be in a different package:.PP.Vb 1\& somefunction("&main::LOGFILE");.Ve.PPThis way if \fIsomefunction()\fR is planning on opening its argument, it canjust use the already opened handle. This differs from passing a handle,because with a handle, you don't open the file. Here you have somethingyou can pass to open..PPIf you have one of those tricky, newfangled I/O objects that the \*(C+folks are raving about, then this doesn't work because those aren't aproper filehandle in the native Perl sense. You'll have to use \fIfileno()\fRto pull out the proper descriptor number, assuming you can:.PP.Vb 4\& use IO::Socket;\& $handle = IO::Socket::INET\->new("www.perl.com:80");\& $fd = $handle\->fileno;\& somefunction("&$fd"); # not an indirect function call.Ve.PPIt can be easier (and certainly will be faster) just to use realfilehandles though:.PP.Vb 4\& use IO::Socket;\& local *REMOTE = IO::Socket::INET\->new("www.perl.com:80");\& die "can\*(Aqt connect" unless defined(fileno(REMOTE));\& somefunction("&main::REMOTE");.Ve.PPIf the filehandle or descriptor number is preceded not just with a simple\&\*(L"&\*(R" but rather with a \*(L"&=\*(R" combination, then Perl will not create acompletely new descriptor opened to the same place using the \fIdup\fR\|(2)system call. Instead, it will just make something of an alias to theexisting one using the fdopen(3S) library call. This is slightly moreparsimonious of systems resources, although this is less a concernthese days. Here's an example of that:.PP.Vb 2\& $fd = $ENV{"MHCONTEXTFD"};\& open(MHCONTEXT, "<&=$fd") or die "couldn\*(Aqt fdopen $fd: $!";.Ve.PPIf you're using magic \f(CW\*(C`<ARGV>\*(C'\fR, you could even pass in as acommand line argument in \f(CW@ARGV\fR something like \f(CW"<&=$MHCONTEXTFD"\fR,but we've never seen anyone actually do this..Sh "Dispelling the Dweomer".IX Subsection "Dispelling the Dweomer"Perl is more of a DWIMmer language than something like Java\*(--where \s-1DWIM\s0is an acronym for \*(L"do what I mean\*(R". But this principle sometimes leadsto more hidden magic than one knows what to do with. In this way, Perlis also filled with \fIdweomer\fR, an obscure word meaning an enchantment.Sometimes, Perl's DWIMmer is just too much like dweomer for comfort..PPIf magic \f(CW\*(C`open\*(C'\fR is a bit too magical for you, you don't have to turnto \f(CW\*(C`sysopen\*(C'\fR. To open a file with arbitrary weird characters init, it's necessary to protect any leading and trailing whitespace.Leading whitespace is protected by inserting a \f(CW"./"\fR in front of afilename that starts with whitespace. Trailing whitespace is protectedby appending an \s-1ASCII\s0 \s-1NUL\s0 byte (\f(CW"\e0"\fR) at the end of the string..PP.Vb 2\& $file =~ s#^(\es)#./$1#;\& open(FH, "< $file\e0") || die "can\*(Aqt open $file: $!";.Ve.PPThis assumes, of course, that your system considers dot the currentworking directory, slash the directory separator, and disallows \s-1ASCII\s0NULs within a valid filename. Most systems follow these conventions,including all \s-1POSIX\s0 systems as well as proprietary Microsoft systems.The only vaguely popular system that doesn't work this way is the\&\*(L"Classic\*(R" Macintosh system, which uses a colon where the rest of ususe a slash. Maybe \f(CW\*(C`sysopen\*(C'\fR isn't such a bad idea after all..PPIf you want to use \f(CW\*(C`<ARGV>\*(C'\fR processing in a totally boringand non-magical way, you could do this first:.PP.Vb 10\& # "Sam sat on the ground and put his head in his hands. \& # \*(AqI wish I had never come here, and I don\*(Aqt want to see \& # no more magic,\*(Aq he said, and fell silent."\& for (@ARGV) { \& s#^([^./])#./$1#;\& $_ .= "\e0";\& } \& while (<>) { \& # now process $_\& }.Ve.PPBut be warned that users will not appreciate being unable to use \*(L"\-\*(R"to mean standard input, per the standard convention..Sh "Paths as Opens".IX Subsection "Paths as Opens"You've probably noticed how Perl's \f(CW\*(C`warn\*(C'\fR and \f(CW\*(C`die\*(C'\fR functions canproduce messages like:.PP.Vb 1\& Some warning at scriptname line 29, <FH> line 7..Ve.PPThat's because you opened a filehandle \s-1FH\s0, and had read in seven recordsfrom it. But what was the name of the file, rather than the handle?.PPIf you aren't running with \f(CW\*(C`strict refs\*(C'\fR, or if you've turned them offtemporarily, then all you have to do is this:.PP.Vb 4\& open($path, "< $path") || die "can\*(Aqt open $path: $!";\& while (<$path>) {\& # whatever\& }.Ve.PPSince you're using the pathname of the file as its handle,you'll get warnings more like.PP.Vb 1\& Some warning at scriptname line 29, </etc/motd> line 7..Ve.Sh "Single Argument Open".IX Subsection "Single Argument Open"Remember how we said that Perl's open took two arguments? That was apassive prevarication. You see, it can also take just one argument.If and only if the variable is a global variable, not a lexical, youcan pass \f(CW\*(C`open\*(C'\fR just one argument, the filehandle, and it will get the path from the global scalar variable of the same name..PP.Vb 5\& $FILE = "/etc/motd";\& open FILE or die "can\*(Aqt open $FILE: $!";\& while (<FILE>) {\& # whatever\& }.Ve.PPWhy is this here? Someone has to cater to the hysterical porpoises.It's something that's been in Perl since the very beginning, if notbefore..Sh "Playing with \s-1STDIN\s0 and \s-1STDOUT\s0".IX Subsection "Playing with STDIN and STDOUT"One clever move with \s-1STDOUT\s0 is to explicitly close it when you're donewith the program..PP.Vb 1\& END { close(STDOUT) || die "can\*(Aqt close stdout: $!" }.Ve.PPIf you don't do this, and your program fills up the disk partition dueto a command line redirection, it won't report the error exit with afailure status..PPYou don't have to accept the \s-1STDIN\s0 and \s-1STDOUT\s0 you were given. You arewelcome to reopen them if you'd like..PP.Vb 2\& open(STDIN, "< datafile")\& || die "can\*(Aqt open datafile: $!";\&\& open(STDOUT, "> output")\& || die "can\*(Aqt open output: $!";.Ve.PPAnd then these can be accessed directly or passed on to subprocesses.This makes it look as though the program were initially invokedwith those redirections from the command line..PPIt's probably more interesting to connect these to pipes. For example:.PP.Vb 3\& $pager = $ENV{PAGER} || "(less || more)";\& open(STDOUT, "| $pager")\& || die "can\*(Aqt fork a pager: $!";.Ve.PPThis makes it appear as though your program were called with its stdoutalready piped into your pager. You can also use this kind of thingin conjunction with an implicit fork to yourself. You might do thisif you would rather handle the post processing in your own program,just in a different process:.PP.Vb 4\& head(100);\& while (<>) {\& print;\& } \&\& sub head {\& my $lines = shift || 20;\& return if $pid = open(STDOUT, "|\-"); # return if parent\& die "cannot fork: $!" unless defined $pid;\& while (<STDIN>) {\& last if \-\-$lines < 0;\& print;\& } \& exit;\& }.Ve.PPThis technique can be applied to repeatedly push as many filters on youroutput stream as you wish..SH "Other I/O Issues".IX Header "Other I/O Issues"These topics aren't really arguments related to \f(CW\*(C`open\*(C'\fR or \f(CW\*(C`sysopen\*(C'\fR,but they do affect what you do with your open files..Sh "Opening Non-File Files".IX Subsection "Opening Non-File Files"When is a file not a file? Well, you could say when it exists butisn't a plain file. We'll check whether it's a symbolic link first,just in case..PP.Vb 3\& if (\-l $file || ! \-f _) {\& print "$file is not a plain file\en";\& }.Ve.PPWhat other kinds of files are there than, well, files? Directories,symbolic links, named pipes, Unix-domain sockets, and block and characterdevices. Those are all files, too\*(--just not \fIplain\fR files. This isn'tthe same issue as being a text file. Not all text files are plain files.Not all plain files are text files. That's why there are separate \f(CW\*(C`\-f\*(C'\fRand \f(CW\*(C`\-T\*(C'\fR file tests..PPTo open a directory, you should use the \f(CW\*(C`opendir\*(C'\fR function, thenprocess it with \f(CW\*(C`readdir\*(C'\fR, carefully restoring the directory name if necessary:.PP.Vb 5\& opendir(DIR, $dirname) or die "can\*(Aqt opendir $dirname: $!";\& while (defined($file = readdir(DIR))) {\& # do something with "$dirname/$file"\& }\& closedir(DIR);.Ve.PPIf you want to process directories recursively, it's better to use theFile::Find module. For example, this prints out all files recursivelyand adds a slash to their names if the file is a directory..PP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -