更新时间:2024-10-25 15:31
档案存取指MP3本身除了存储MP3音乐之外,是否还可以作为移动存(U盘)使用,这样可以进行各种格式文件的下载、上传,也可以在硬碟里存放简报、照片、文件以及数码影片等等。对于MP3的档案存取功能来说,Windows98及98以下的操作系统需要安装随机的驱动程序;而Windows2000、XP、ME等系统不需要安装驱动程序,系统就会自动识别。
存储:分成无驱和有驱型两种。大部分MP3出于版权保护的考虑,要求使用自带的管理程序实现MP3机和电脑间的文件上传、下载。MP3一般对非音乐格式的文件都支持档案管理,就是可以实现这些文件的上传、下载。而是否需要安装驱动,只影响具体使用环境——如果是固定电脑,即便有驱动也无所谓;如果是经常在不同电脑间转移文件的,当然推荐无驱型的了,毕竟免除了安装管理程序的烦恼(这里的无驱也是相对WIN98后的操作系统而言)。
档案系统在写程式时是非常重要的一个部份,尤其对于Perl的使用者来说,因为Perl能够处理大量而且复杂的资料,所以经常被拿来作为Unix作业系统的管理工具,尤其对于Unix-like系统管理员而言,在进行系统日志的管理时,存取档案,读取档案内容并加以分析就是最基本的部分。当然,你还可能进行目录的修改,档案权限的维护等等跟系统有密切关系的操作。
当你的Perl想要透过作业系统进行档案存取时,可以利用档案代号取得和档案间的系结,接下来的操作就是透过这个档案代号和实体的档案间进行沟通。也就是说,我们要进行档案操作时,可以先定义相对应实体档案的代号,以便我们用更简便的方式对档案进行存取。
而所谓的档案代号其实就是由使用者自行命名,并且用来跟实体档案进行连结的名称,他的命名规则还是依循Perl的命名规则,大家对于这个规则应该相当熟悉了,不过我们还是再次提醒一下:可以数字,字母及底线组成,但是不能以数字作为开始。而且一般来说,我们几乎都习惯以全部大写来作为档案代号,因为档案代号并不像其他变数,会使用某些符号作为识别,所以几乎约定成俗的全部大写习惯也是有存在的道理。
当然,你也可以依照自己的习惯来为档案代号命名(注一),这表示所谓的全部大写绝对不是一种铁律,就像Perl程式语言本身,希望以最少的限制来进行程式设计的工作。
对于档案的输出,输入而言,其实就跟平常时候,你利用Perl在进行其他的操作非常接近,有时候只是输出到不同的媒介上。所以Perl其实已经预定了几种档案代号,让你不需要每次写Perl的程式就必须去重新定义这些代号,很显然的,几乎大部份的程式都会需要这些档案代号。
这六个预设的档案代号分别是:STDIN,STDOUT,STDERR,DATA,ARGV,ARGOUT,看起来相当熟悉吧?没错,因为很多时候,我们其实就是靠这些预设的档案代号在进行程式的输出,输入。只是我们还没有了解这些其实就是档案代号。换个角度来看,其实即使我们都不知道他们是预设的档案代号,我们就能运作自如,那么对于档案代号的使用显然就不是太难。不过,我们还是要再来看看这六个Perl预设的档案代号。其中有些我们已经使用过了,我们就先对其中几个预设的档案代号来进行介绍:
STDIN:这也就是我们常看到的“标准输入装置”,当Perl开始执行时,它预设接受的外部资讯就是从这里而来。就像我们之前曾经看过的写法:
my =
print ;
这时候,当我们从键盘输入时,Perl就可以正确的取得资讯,并且透过STDIN取得使用者用键盘打入的一行字串。因此他的运作方式就是以一个档案代号来进行。当然,你可以透过系统函式库的配合,让你的标准输入转为其他设备之后你就进行其他运用,不过这显然不是这里的主题,还是让我们言归正传。对于Perl来说,他从档案系统读入资料是以行为单位,因此即使是利用STDIN,Perl还是会等到使用者键入换行键时才会有所动作。
STDOUT:相对于标准输入,这就是所谓的标准输出,也就是在正常状况下,你希望Perl输出的结果就是透过STDOUT来进行输出的。而一般来说,我们所使用的就是荧幕输出。你可以看看这个程式里的写法:
没错,就像我们所预期的,Perl透过荧幕印出了两行一模一样的结果,也就是印了两行“标准输出”。原因非常简单,因为当我们使用print的指令时,Perl会使用STDOUT当作预设的档案代号,所以一般状况下,如果我们没有指定档案代号时,Perl就会自动输出到STDOUT。所以事实上,我们早就开始使用档案代号了,只是我们自己并没有发觉。或说,Perl原来的期望就是希望使用者都可以在最没有负担的状况下任意输出到荧幕,或从键盘输入,毕竟Perl程式设计师那么的怕麻烦,一般的键盘输入,荧幕输出又是使用的那么频繁,当然要让程式设计师以最简单的方式达成。而且非常显然,这个目的也算达到了。
STDERR:标准的错误串流,也就是程式错误的标准输出。正常而言,当程式发生错误时,程式可以发出错误讯息来通知使用者,这时候这些错误讯息也能透过档案代号处理,把这些讯息丢进错误讯息串流。不过这样说实在不太容易理解,那我们来玩个游戏吧:
我们一开始定义了一个字串,一开始我们先直接从标准输出印出这个字串,接下来我们便要求Perl把这个字串送出到错误串流中。这样会发生甚么有趣的事呢?让我们来看看:
[hcchien@Apple]% perl
标准输出
标准输出
[hcchien@Apple]% perl s> error.txt
标准输出
ARGV:我们可以直接利用参数来读取某些档案的内容,使用者只需要在执行程式时,在程式后加上档案名称作为参数,然后在程式中我们就可以直接读到档案的内容了。还是用个例子比较容易理解:
my =
[hcchien@Apple]% perl > error.txt
标准输出
没错,当我们用了刚刚得到的error.txt当参数时,程式里面直接使用预设档案代号ARGV来读取档案内容,所以当我们印出来时,就可以看到刚刚写入档案的内容了。不过由于Perl读档案的性质,其实我们只印出了档案内的第一行,不过这部份我们稍后会再提到,这里暂且略过不谈。
不过Perl的ARGV其实非常好用,让我们来看看使用阵列形式的@ARGV。也就是程式的参数,跟我们曾经提过的副常式参数有几分相似。它也是把取得的参数放入阵列中,然后在程式里,就可以直接叫用阵列,取出参数,就像这样:
my = shift @ARGV;
我们用同样的方式执行,可以看到这样的结果:
[hcchien@Apple]% perl error.txt
error.txt
另外,我们也可以对ARGV进行一般档案代号的操作方式,不过这些将在稍后提到档案操作时再来讨论。
我们刚刚提到了一些Perl预设的档案代号,这些档案代号都是由Perl自动产生的。因此当我们开始执行Perl的程式时,就可以直接使用这些档案代号。可是除此之外,当我们希望自己来对某些档案进行存取时,就必须手动控制某些程序。所以应该来关心一下,当我们要手动进行这些档案的控管时,应该怎么做呢?
10.3.1 开档/关档
最基本的,我们要先开启一个档案,也就是我们必须将档案代号和我们想要存取的档案接上线。首先,我们可以使用open这个指令来开启档案代号,并且指定这个档案代号所对应的档案名称,所以我们使用的指令应该会会这样:
其实要开起一个档案代号非常的容易,至少从上面的例子来看,应该还算是非常的平易近人。那么我们只需要稍微的解释一些特殊的部份,大部份的人应该就可以轻松的开始使用档案代号了。
既然你开启了一个档案代号,最好的方式就是在你使用完后要归回原处(从小妈妈就这么告诫我们)。因此如果你不再使用某个档案代号时,你最好养成关闭这些档案代号的习惯,对了,应该还要提醒的是“适时”关闭不需要的档案代号。虽然Perl会在程式结束时自动帮你关闭所有还开着的档案代号,不过有些时候,你如果没有在档案处理完之后就尽快处理的话,恐怕会有让系统资源的负担增加。
至于关闭档案代号的方式也是非常简单,你只要使用close这个关键字,然后告诉Perl你所要关闭的档案代号,这样就没问题了。因此你如果需要关闭档案代号,你只需要这么做:
close FILE;
没错,就是这么容易。不过却也相当重要,至少你应该考虑好你自己的系统资源管理。否则等到等到持续拖累系统资源时才要怪罪Perl时可就有失公允了。另外,Perl也会在你关闭档案代号时检查缓冲区是否还存有资料,如果有的话,Perl也会先把资料写入档案,然后关闭档案。另外,档案也可能因为你的开启而导致其他人无法对它正常的操作,因此尽可能在完成档案操作后马上关闭档案代号是重要的习惯。
10.3.2 意外处理
有些时候,当我们想要开启档案时却会发现一些状况。例如我们想要从某个已经存在的档案中读入某些资料,可是却发生档案不存在,或是权限不足,而无法读入的状况。我们先看看以下的例子:
#!/usr/local/bin/perl
use strict;
while (
print ;
}
die函式就像他的字面意思,他可以让程式停止执行,也就是让程式“死去”。因此当我们希望程式在某些状况下应该停止执行时,我们就可以使用die函式来达成。而档案发生问题的状况则是die函式经常被使用的地方。因为很多时候我们一旦开启了某个档案,大多就会把操作内容围绕着这个被开启的档案,可是如果档案其实没有被正确的开启,就很容易产生一些难以预料的问题,因此我们可以在档案开启失败时就让程式停止执行。以刚刚的程式作为例子,我们就可以把开启档案的部份写成:
所以如果我们执行刚刚改过的那个程式,就可以得到像这样的结果:
[hcchien@Apple]% perl
开启档案失败: No such file or directory atline 5.
因为档案不存在的原因,导致这一支Perl程式无法继续执行而在执行完die之后就停止了。而且die这个指令也在我们的要求下,传达了系统的错误讯息给我们,问题发生在你要开启档案时却没有发现这个档案或资料夹。所以利用die这个指令,你就可以在程式无法正确开启档案时,就马上中断程式,以避免不可预知的问题产生。
#!/usr/local/bin/perl
use strict;
while (
print ;
}
你应该发现了,我们把die改成了warn,然后最后加了一行列印的指令,告诉我们程式的结尾在那里。接下来我们来试着执行这支修改过的程式,你会看到这样的结果:
[hcchien@Apple]% per
open failed: No such file or directory at line 5.
the end of the script
10.3.3 读出与写入
在我们可以正确的开启档案代号之后,接下来我们就可以开始存取档案中的资料,当然最主要的就是读取,以及写入档案。
透过档案代号来读取档案内容倒是不太有甚么困难。我们大多使用钻石符号(<>;)来进行档案内容的读取。所以我们可以像这样进行档案操作:
#!/usr/local/bin/perl -w
use strict;
while (
print if (/sudo/); # 符合比对的资料就列印出来
}
看起来非常容易,不是吗?
接下来我们透过钻石符号开始逐行读取日志档案中的资料,透过回圈while读取档案中的资料时,while会把所读到的资料内容放进Perl的预设变数中,一直到档案结束,传回EOF时,回圈便会结束。因此我们就将所读取的资料进行比对,以sudo这个关键字作为比对样式,把符合的结果印出来。
这样一来,只要系统中有人使用sudo进行系统操作时,我们就可以检查出来,而且印出来的结果会像是这样:
TTY=ttyp0 ; PWD=/var/log ; USER=root ; COMMAND=/bin/rm -rf httpd-error.log
TTY=ttyp0 ; PWD=/var/log ; USER=root ; COMMAND=/bin/rm -rf httpd-access.log
TTY=ttyp0 ; PWD=/var/log ; USER=root ; COMMAND=/bin/rm -rf 192.168.1.1_access_log
192.168.1.1_error_log
TTY=ttyp0 ; PWD=/usr/home ; USER=root ; COMMAND=/bin/rm -rf interchange/
TTY=ttyp0 ; PWD=/usr/home ; USER=root ; COMMAND=/bin/rm -rf gugod/
TTY=ttyp0 ; PWD=/usr/home ; USER=root ; COMMAND=/bin/rm -rf mysql/
TTY=ttyp0 ; PWD=/ ; USER=root ; COMMAND=/bin/rm kernel.old
TTY=ttyp0 ; PWD=/ ; USER=root ; COMMAND=/bin/rm -rf modules.old/
TTY=ttyp0 ; PWD=/ ; USER=root ; COMMAND=/bin/rm -rf opt/
如果你是负责管理一些Unix的伺服器,利用这样简单的方式,确实可以帮忙你完成不少工作。很显然,利用档案的操作,你还可以进行更多对日志档案的分析。例如你可以分析网站伺服器的各项资料,虽然其实已经有很多人用Perl帮你完成这样的工作了。(注二)
基本上,从档案内读取内容的方式就是这么容易,因此你可以简单的运用档案的内容进行所需要的工作。还记得我们在介绍open时的说明吗?我们有几个开启档案的方式包括了几种描述子,例如大于(>;),小于(<;),以及两个大于(>>;)。而且我们也都简单的描述过他们的差异,也许就是测试这些描述子的好时机,我们先来看看小于符号用于开档的时候,会有甚么影响。
我们之前也提过小于符号用在开档作为描述的话,是用来表示从档案内读取资料。那我们是不是就只能允许使用者读取资料呢?先来看看这个小小的程式吧:
while (
print ;
}
file for log
Bad file descriptor at line 9,
第一行就是原来log.txt里面的内容,我们可以很轻松的读出其中的资料,并且印出来,可是当我们要将资料写入时,却出现了错误讯息。没错,当初我们在开启这个档案时,只要求Perl给我们一个可以读出资料的档案,如今要求写入,果然就遭到拒绝。
看来一但我们使用了小于符号作为开启档案代号的描述子,那么我们就不能轻易的把资料写入所开启的档案中。想当然尔,Perl应该也不会让我们在开启一个利用大于符号指定为写入的档案中把资料读出吧?要想测试这样的结论,我们只需要把刚刚的程式修改一个字元,也就是把小于符号改成大于,那么就让我们来看看执行后的结果吧:
既然使用大于符号跟小于符号都符合我们的期待,那么如果我们甚么描述子都没有使用,会是甚么样的情况呢?我们只需要使用刚刚的测试程式,并且把描述子全部取消,再来试试结果如何吧!
结果我们发现,Perl还是可以读出档案的内容,可是却无法写入。也就是跟我们使用小于符号时是一样的状况,这点其实对于经常必须使用档案的人来说其实是非常重要的。所以如果你有机会使用档案的存取时,可别忘了这一点。
另外,大于符号与两个大于的差别我们也曾经提过,这部份对于可能使用Perl来进行日常管理工作的人更是必须牢记。我们之前提过,一样是开启一个可以写入的档案,使用一个大于符号(>;)的时候,Perl会判断你是否已经有存在这个档名的档案,如果档案已经存在,那么Perl将会清空档案内容,把他视作一个新的档案来进行操作。如果在系统中档案并不存在,那么Perl就会跟系统要求开启一个新的档案。当然,在你使用两个大于符号的时候,Perl会把你要写入档案的内容以附加的方式存入。当然,如果你的系统中并没有这个档案,那么Perl也会先开启一个新档,并且把你所要求的内容写入档案中。这对于想要建立类似日志档的需求有着绝对的帮助,例如你可能会需要Perl来作为监控网路的状况,这时候你会需要每次有新状况时就把它记录下来,而且需要保留原来的纪录。那么如果你还是使用大于符号的话,你可就要小心原来的资料内容遗失了。
当然,我们知道开启档案时可以利用三种描述子去指定所要开启档案代号的状态,不过如果你甚么都没加的状况下,Perl又会作怎么样的处理呢?我们继续用刚刚的例子来进行实验吧。我们把开启档案的描述子拿掉,其他的部份一切照旧。所以你的程式就像这样:
接着我们发现,这样的结果就跟我们使用小于符号的效果是相同的,也就是Perl只会从档案中读出资料,却无法写入。
有了基本读写档案的能力之后,我们还必须了解该怎么样透过Perl去控制系统的档案以及资料夹。这样才能确实掌握系统的档案管理,尤其当你希望使用Perl来进行系统管理时,也就会更需要这样的能力,所以我们接下来就要讨论利用Perl对档案系统的操作。
注一:不过当你打算这么作的时候,也许要考虑这支程式未来只有你在维护,否则你这样的动作很可能会因为接下来维护的人需要花更多的时间来看懂程式而提高不少维护成本。
注二:其实跟这章主题不太有关,不过例如awstats就是这类型的工具。
使用权限 : 所有使用者
使用方式 : chmod [-cfvR] [--help] [--version] mode file...
说明 : Linux/Unix 的档案存取权限分为三级 : 档案拥有者、群组、其他。利用 chmod 可以藉以控制档案如何被他人所存取。
把计 :
mode : 权限设定字串,格式如下 : [ugoa...][[+-=][rwxX]...][,...],其中u 表示该档案的拥有者,g 表示与该档案的拥有者属于同一个群体(group)者,o 表示其他以外的人,a 表示这三者皆是。
+ 表示增加权限、- 表示取消权限、= 表示唯一设定权限。
r 表示可读取,w 表示可写入,x 表示可执行,X 表示只有当该档案是个子目录或者该档案已经被设定过为可执行。
-c : 若该档案权限确实已经更改,才显示其更改动作
-f : 若该档案权限无法被更改也不要显示错误讯息
-v : 显示权限变更的详细资料
-R : 对目前目录下的所有档案与子目录进行相同的权限变更(即以递回的方式逐个变更)
--help : 显示辅助说明
--version : 显示版本
范例 :将档案 file1.txt 设为所有人皆可读取 :
chmod ugo+r file1.txt
将档案 file1.txt 设为所有人皆可读取 :
chmod a+r file1.txt
将档案 file1.txt 与 file2.txt 设为该档案拥有者,与其所属同一个群体者可写入,但其他以外的人则不可写入 :
chmod ug+w,o-w file1.txt file2.txt
将 ex1.py 设定为只有该档案拥有者可以执行 :
chmod u+x ex1.py
将目前目录下的所有档案与子目录皆设为任何人可读取 :
chmod -R a+r *
此外chmod也可以用数字来表示权限如 chmod 777 file
语法为:chmod abc file
其中a,b,c各为一个数字,分别表示User、Group、及Other的权限。
r=4,w=2,x=1
若要rwx属性则4+2+1=7;
若要rw-属性则4+2=6;
若要r-x属性则4+1=7。
范例:
chmod a=rwx file
和
chmod 777 file
效果相同
chmod ug=rwx,o=x file
和
chmod 771 file
效果相同
若用chmod 4755 filename可使此程式具有root的权限
指令名称 : chown
使用权限 : root
使用方式 : chmod [-cfhvR] [--help] [--version] user[:group] file...
说明 : Linux/Unix 是多人多工作业系统,所有的档案皆有拥有者。利用 chown 可以将档案的拥有者加以改变。一般来说,这个指令只有是由系统管理者(root)所使用,一般使用者没有权限可以改变别人的档案拥有者,也没有权限可以自己的档案拥有者改设为别人。只有系统管理者(root)才有这样的权限。
把计 :
user : 新的档案拥有者的使用者 IDgroup : 新的档案拥有者的使用者群体(group)-c : 若该档案拥有者确实已经更改,才显示其更改动作-f : 若该档案拥有者无法被更改也不要显示错误讯息-h : 只对于连结(link)进行变更,而非该 link 真正指向的档案-v : 显示拥有者变更的详细资料-R : 对目前目录下的所有档案与子目录进行相同的拥有者变更(即以递回的方式逐个变更)--help : 显示辅助说明--version : 显示版本
范例 :
将档案 file1.txt 的拥有者设为 users 群体的使用者 jessie :
chown jessie:users file1.txt
将目前目录下的所有档案与子目录的拥有者皆设为 users 群体的使用者 lamport :
chmod -R lamport:users *
-rw------- (600) -- 只有属主有读写权限。
-rw-r--r-- (644) -- 只有属主有读写权限;而属组用户和其他用户只有读权限。
-rwx------ (700) -- 只有属主有读、写、执行权限。
-rwxr-xr-x (755) -- 属主有读、写、执行权限;而属组用户和其他用户只有读、执行权限。
-rwx--x--x (711) -- 属主有读、写、执行权限;而属组用户和其他用户只有执行权限。
-rw-rw-rw- (666) -- 所有用户都有文件读、写权限。这种做法不可取。
-rwxrwxrwx (777) -- 所有用户都有读、写、执行权限。更不可取的做法。
以下是对目录的两个普通设定:
drwx------ (700) - 只有属主可在目录中读、写。
drwxr-xr-x (755) - 所有用户可读该目录,但只有属主才能改变目录中的内容
suid的代表数字是4,比如4755的结果是-rwsr-xr-x
sgid的代表数字是2,比如6755的结果是-rwsr-sr-x
sticky位代表数字是1,比如7755的结果是-rwsr-sr-t