Perl文件目录操作函数介绍
2013-04-28 17:34:17

Perl has a number of built-in functions that can manipulate the filesystem.Perl有不少内建或核心模块是关于文件操作的,大致可分为三类:

The file input and output functions-文件输入、输出操作
 
The directory-manipulation functions-目录管理
 
The file-attribut manipulation functions-文件属性管理


Perl内置了以下一些操作目录的标准函数:
opendir DIRHANDLE, EXPR # 打开目录
readdir DIRHANDLE # 读取目录
rewinddir DIRHANDLE # 定位指针到开头
telldir DIRHANDLE # 返回目录的当前位置
seekdir DIRHANDLE, POS # 定位指定到目录的 POS 位置
closedir DIRHANDLE # 关闭目录


1、File Input and Output Functions-文件输入、输出操作

1)、Opening Pipes--管道操作

Two commands can be linked using a pipe. The first commands standard output is piped (linked) to the second connads standard input. To do this we need to associate the file with the command by calling open.

两个指令通过管道来连接,第一个指令的标准输出通过管道做为第二个指令标准输入。这与我们通过调用open函数来关联文件一样。

Opening pipe example(output)
open (MESAAGE, "| mail freeoa@im168.us");
print MESSAGE ("Hello how is the website coming along?");
close (MESSAGE);

Note: The call to open establishes a pipe to the command "mail freeoa@im168.us", the file variable MESSAGE is now associated with this pipe. The call to print add the line to the message to be sent. The call to close closes the pipe and the mail program can then send the mail message.

注意:这里调用了open来建立了与'mail freeoa@im168.us'这个指令的管道,MESSAGE这个文件句柄就通过它关联了起来。然后调用print函数来增加一行内容到其中。接下来调用close函数来关闭管道,mail指令就可以发出内容了。

Opening pipe example(input)
open (CAT, "cat file*|");
$input = <CAT>;## variable input will now have the cat'ed contents of all the files

2)、Redirecting One File to Another--选择文件句柄

Unix allows you to direct both the standard outfile file and the standard error file to the same output file. You can also perform the same task with Perl.

Unix允许直接将标准输出和标准错误输出到同一个文件,当然Perl也可以做同样的事情。

Redirecting example
open (STDOUT, ">file1") || die("ERROR: open STDOUT failed");
open (STDERR, ">&SDOUT") || die ("ERROR: open STDERR failed");

$| = 1;## turn buffering off for STDOUT
select (STDERR);## change the default file to STDERR (normal default file is STDOUT)
$| = 1;## turn buffer off for STDERR

print STDOUT ("Line One\n");
print STDERR ("Line Two\n");

close(STDOUT);
close(STDERR);

3)、Select Function-select 函数

This allows you to select a new default file, so that calls to print, write and printf write to file variable STDERR, unless a file variable is explicity specified.

这将允许你选择一个新的默认文件,接下来便可调用print,write,printf来进行对文件的写操作到错误输出,除非进行了指定到其它文件。

Select 示例
select (STDERR);## This becomes the new default file

4)、eof Function-eof 函数


The eof function checks whether the last input file read has been exhausted, eof returns a non-zero value when all the file has been read.

eof函数检查对文件的读取是否用尽,当文件的所有记录被读取时返回非零值。
    
while($line = <>){
 print($line);
 if (eof) {## the eof returns a non-zero value, thus executing the if statement
  print ("------ END OF FILE CONTENTS -------\n");
 }
}

Note: you can use the eof() function as well, so you could do eof(MYFILE)

5)、Seek and Tell--文件定位

Perl provides two functions which enable you to skip forward or backward in a file so that you can skip or re-read data.

Perl提供了两个函数来允许你向前或后跳过若干行,或重读某些数据。

seek - moves backward or forward(基于行的移动)
tell - returns the distance in bytes, between the beginning of the file and the current position of the file(基于文件大小byte的移动)


seek 函数

seek()函数是通过文件句柄来移动文件读写指针的方式来读取或写入文件的,以字节为单位进行读取和写入:
seek FILEHANDLE, POSITION, WHENCE

参数说明:
FILEHANDLE:文件句柄,用于存放一个文件唯一标识符。
POSITION:表示文件句柄(读写位置指针)要移动的字节数。
WHENCE:表示文件句柄(读写位置指针)开始移动时的起始位置,可以取的值为0、1、2;分别表示文件开头、当前位置和文件尾。

以下示例为从文件开头读取 256 个字节:
seek DATA, 256, 0;

seek(MYFILE, 0, 0);## skip to beginning of file
seek(MYFILE, 0, 2);## skip to the end of the file

seek(MYFILE, 80, 1); ## skip forward 80 bytes
seek(MYFILE, -80, 1); ## skip backward 80 bytes


tell 函数用于获取文件位置:
tell FILEHANDLE
tell

如果指定 FILEHANDLE 该函数返回文件指针的位置,以字节计。如果没有指定则返回默认选取的文件句柄。

$offset = tell(MYFILE);

6)、System Read and Write Functions--使用系统的读写函数

Perl provides two other functions that read an input file and one function that can write to a file, use these functions if you want fast read and write speeds.

Perl 提供两个读取函数和一个写函数来处理文件,使用它们便可快速的读写文件。

read - which is equivalent to the Unix fread function
sysread - which is equivalent to the read function
syswrite - calls the Unix write function


read example
read (MYFILE, $scalar, 80);## read 80 bytes and store in variable $scalar

## Appending to an existing scalar variable
read (MYFILE, $scalar, 40, 80);## read 40 bytes, skip 80 bytes in $scalar then append to $scalar

sysread example
sysread (MYFILE, $scalar, 80);## read 80 bytes and store in variable $scalar

## Appending to an existing scalar variable
sysread (MYFILE, $scalar, 40, 80); ## read 40 bytes, skip 80 bytes in $scalar then append to $scalar

syswrite example
syswrite (MYFILE, $scalar, 80);## read 80 bytes and store in variable $scalar

## Appending to an existing scalar variable
sysread (MYFILE, $scalar, 40, 80);
## read 40 bytes, skip 80 bytes in $scalar then append to $scalar

Reading Characters using getc-使用getc函数按字符读取

This function reads a single character of input from a file, this can be useful for "hot key" applications. These applications process one character at a time, instead one line at a time.

该函数用于从输入或文件中读取单个字符,常用于'hot key'应用。它一次处理一个字符而不用一行。

getc example
while(1){
 $char = getc(STDIN);
 last if ($char eq "\\");## remember the first \ is escaping the second \
 print ($char);
}


7)、读写文件的方法的总结

向文件读写信息有以下几种不同的方式:
<FILEHANDL> 操作符

从打开的文件句柄读取信息的主要方法是 <FILEHANDLE> 操作符,在标量上下文中,它从文件句柄返回单一行。例如:

print "FreeOA\n";
$name = <STDIN>;
print "网址:$name\n";


当我们使用 <FILEHANDLE> 操作符时,它会返回文件句柄中每一行的列表,例如我们可以导入所有的行到数组中。创建 import.txt 文件,内容如下:
$ cat import.txt
1
2
3

读取 import.txt 并将每一行放到 @lines 数组中:
open(DATA,"<import.txt") or die "无法打开数据";
@lines = <DATA>;
print @lines;# 输出数组内容
close(DATA);


getc 函数

getc 函数从指定的 FILEHANDLE 返回单一的字符,如果没指定返回 STDIN:

getc FILEHANDLE
getc

如果发生错误,或在文件句柄在文件末尾,则返回 undef。


read 函数

read 函数用于从缓冲区的文件句柄读取信息,这个函数用于从文件读取二进制数据。

read FILEHANDLE, SCALAR, LENGTH, OFFSET
read FILEHANDLE, SCALAR, LENGTH

参数说明:
FILEHANDLE:文件句柄,用于存放一个文件唯一标识符。
SCALAR:存贮结果,如果没有指定OFFSET,数据将放在SCALAR的开头。否则数据放在SCALAR中的OFFSET字节之后。
LENGTH:读取的内容长度。
OFFSET:偏移量。

如果读取成功返回读取的字节数,如果在文件结尾返回 0,如果发生错误返回 undef。


print 函数

对于所有从文件句柄中读取信息的函数,在后端主要的写入函数为 print。

print FILEHANDLE LIST
print LIST
print

利用文件句柄和 print 函数可以把程序运行的结果发给输出设备(STDOUT:标准输出),例如:
print "Hello FreeOA!\n";


2、Directory-Manipulation Functions--目录管理函数

mkdir     create a new directory(创建一个新目录)
chdir     set a directory to be the current working directory(切换指定的目录为当前工作目录)
opendir     In order to list a directory you need to open it first(打开目录的句柄)
closedir     When you are fisnihed with a directory you close it(关闭已经打开的目录句柄)
readdir     when a directory is opened you can now read all the filenames or subdirectories within the directory(在已经打开的目录句柄中读取文件和子目录)
telldir DIRHANDLE (返回目录的当前位置)
seekdir DIRHANDLE, POS (定位指定到目录的 POS 位置)
rewinddir     rewind backwards in a directory(在一个目录句柄中倒带,定位指针到开头)
rmdir   remove a directory, the directory must be empty first(删除一个空目录)

示例
mkdir
mkdir ("/data/freeoa", 0777);

chdir
chdir ("/data/freeoa");

opendir
opendir (DIR, "/data/freeoa");

closedir
closedir (DIR);

readdir
$filename = readdir(DIR);## read the first filename of the directory
@files = readdir(DIR);## read all the filenames into an array

telldir and seekdir
$location_path = tell(DIR);## tells where abouts you are in the directory structure

seekdir(DIR, "/data/freeoa");## set DIR to the new location

rewinddir
rewinddir(DIR);

rmdir
rmdir(DIR);## directory must be empty


列出当前目录下的所有文件:
opendir (DIR, '.') or die "无法打开目录, $!";
while ($file = readdir DIR){
  print "$file\n";
}
closedir DIR;

显示 /tmp 目录下所有以 .c 结尾的文件,可以使用以下代码:
opendir(DIR, '.') or die "无法打开目录, $!";
foreach (sort grep(/^.*\.c$/,readdir(DIR))){
   print "$_\n";
}
closedir DIR;

创建一个新目录:
可以使用 mkdir 函数来创建一个新目录,执行前你需要有足够的权限来创建目录:
$dir = "/tmp/perl";
# 在 /tmp 目录下创建 perl 目录
mkdir($dir) or die "无法创建$dir目录, $!";
print "目录创建成功\n";

删除目录:
使用 rmdir 函数来删除目录,执行该操作需要有足够权限。另外要删除的目录必须的空目录:
$dir = "/tmp/perl";

# 删除 /tmp 目录下的 perl 目录
rmdir($dir) or die "无法删除$dir目录, $!";
print "目录删除成功\n";

切换目录:
使用chdir 函数来切换当期目录,执行该操作需要有足够权限:
$dir = "/freeoa";

# 将当期目录移动到 /home 目录下
chdir($dir) or die "无法切换目录到$dir, $!";
print "你现在所在的目录为 $dir\n";

执行以上程序,输出结果为:
你现在所在的目录为 /freeoa


3、File-Attribute Functions--文件属性控制

You can also use a number of the file test-operators with some of the commands below, to see a full listing check the perl cheat sheet.

可以使用一些文件的测试操作符下面的命令,这是一个完整的perl备忘单。

rename:change the name of a file(修改文件名)

unlink and link:use unlink to delete a file and use link to create hard links(删除文件或创建文件链接)

symlink:used to create symbolic links (soft link)(创建软连接)

readlink:returns the filename to which the file is linked to(返回文件被连接后的名称)

chmod:changes access permissions(修改访问权限)

chown:changes the owner of a file(修改文件属主)

umask:sets the default access permissions for a file(设置文件默认的访问权限)

truncate:reduce a files size to a specified length(将文件的大小减到指定)

stat:retrieves information about a particular file(取得指定文件的信息)

lstat:same as stat but presumes that the filename passed is a symbolic link(同上,但能取得被链接文件的信息)

time:to obtain the number of elapsed seconds from Jan 1 1970 to the npresent time, call this function(取得文件的unix时间戳)

gmtime and localtime:convert the value returned by time to either Greenwich Mean Time or your computers local time(返回其格林尼治和本地时间)

utime:set access and modification times of files(设置文件的访问和修改时间)

fileno:return the Inode number of the file(返回文件i节点数)

flock and fcntl:flock is a file locking function and fcntl provides constants for use with various Perl built-in functions(Perl内置的高级文件锁)

示例
rename:rename("file1", "file2"); ## rename file1 to file2

unlink and link     
files_deleted = unlink ("file1", "file2");## delete the files file1 and file2, returns number of## files acutally deleted

link("/u/pvalle/file1", "/u/pvalle/file2");## create a hard link

symlink:symlink("/u/pvalle/file1", "/u/pvalle/file2");

readlink:$linkname = readlink("/u/pvalle/file2");## $linkname will contain the actaully filename

chmod:## chmod (<perms>, <files>);
chmod (0777, "file1");
chmod (0777, @filelist);

chown:# chown (<userid>,<groupid>, <files>);
chown (17, -1, "file1");
chown (17, -1, @filelist);

umask:$oldmask = umask(0022);## $oldmask will contain the old mask value
$current_mask = umask();## get the current mask value

truncate:truncate ("/u/pvalle/logfile.log", 5000);## truncate file to 5000 bytes

stat:stat("/u/pvalle/logfile.log");
Note: stat returns a list detailing information on the file

lstat:lstat("/u/pvalle/logfile.log");

time:$currtime = time();## returned elapsed-seconds value

gmtime and localtime
$timelist = gmtime(time());
print $timelist;

$timelist = localtime(time());
print $timelist;

utime
$acctime = -A "file1";
$modtime = -M "file1";
utime( $acctime, $modtime, "file2");## set the access & modification times the same as file1

fileno
$filedesc = fileno(MYFILE);

flock and fcntl
fcntl (<filevar>,<fcntlrtn>,<value>);
flock (<filevar>,<flockop>);

提示: best to see the Unix man pages for fcntl and flock