shell编程中的判断语句

28 1 月, 2011 by edsionte 无评论 »

在shell编程中,通过if命令来实现判断语句;if命令中的判断条件则通过test命令来完成。因此,本文将集中介绍if命令和test命令的使用方法。

1. 退出状态

对于每一条命令而言,它在执行完毕后就有相应的返回状态,这个返回状态保存在特殊变量?中。当一条命令成功执行后,该命令的返回状态为0;否则,该命令的返回状态为非0。比如:

edsionte@edsionte-laptop:~/shelltest$ cat nothisfile
cat: nothisfile: 没有那个文件或目录
edsionte@edsionte-laptop:~/shelltest$ echo $?
1
edsionte@edsionte-laptop:~/shelltest$ echo $?
0

由于cat命令执行失败,通过echo命令可获得cat命令的返回值为1;再次echo特殊变量?的值可以看到返回状态为0,这正好说明了第一次echo命令成功执行。

2.if命令

if命令的的使用方法如下:

if command_t
then
	commands
fi

command_t是用来进行逻辑判断的命令。如果该命令的的返回状态为0,则执行then和fi之间的命令。除了上述的基本使用方法外,if命令还有以下两种结构。

//if-else
if command_t
then
	commands
else
	commands
fi
//if-elif-else
if command_t1
then
	commands
elif command_t2
then
	commands
else
	commands
fi

上述两种结构理解起来不会很难,其使用方法可参看test命令中的举例。

3. test命令

正如本文一开始说的那样,test命令常用作if命令中的逻辑判断。其使用方法如下:

test expression

其中expression表示要测试的条件,如果该条件为真,则test命令的返回状态为0;否则返回非0。

字符串操作符

操作符=用来判断两个字符串是否相等,其使用方法如下: test str1 = str2 注意test命令的三个参数必须用空格隔开,这样test才能正确的接收到三个参数。现在,我们可以改进上文的lu程序,增加参数判断功能:

edsionte@edsionte-laptop:~/shelltest$ cat lu
# look someone up in the info book
if test "$1" = ""
then
	echo "usage: ./lu arg"
else
	grep "^$1:" info
fi
edsionte@edsionte-laptop:~/shelltest$ ./lu
usage: ./lu arg

如果未输入参数,则提示使用方法。由于=用来判断两个字符串是否相等,因此该判断符对于字符串中的空格很敏感。比如:

edsionte@edsionte-laptop:~/shelltest$ name="edsionte "
edsionte@edsionte-laptop:~/shelltest$ test "$name" = "edsionte"
edsionte@edsionte-laptop:~/shelltest$ echo $?
1

由于对name赋值时edsionte后有一个空格,因此这两个字符串不相等。test命令的返回值为1。 在上述的test命令中,只要涉及到对变量的引用都会加上双引号。通过下述举例可以看到这种使用的好处。

edsionte@edsionte-laptop:~/shelltest$ name=
edsionte@edsionte-laptop:~/shelltest$ test $name = "edsionte"
bash: test: =: 需要单个参数
edsionte@edsionte-laptop:~/shelltest$ test "$name" = "edsionte"
edsionte@edsionte-laptop:~/shelltest$ echo $?
1

当给name赋值为空时,如果没有使用双引号引用该变量,则shell在执行test命令时会认为缺少了第一个字符串参数。

另一种格式

由于if命令在shell编程中频繁使用,因此也诞生了一种简易的test使用格式:

[ expression ]

其实上述格式中的[和]就等价于命令名。值得注意的是,expression前后需要和相应中括号用空格隔开。比如上述举例:

edsionte@edsionte-laptop:~/shelltest$ [  "$name" = "edsionte"  ]
edsionte@edsionte-laptop:~/shelltest$ echo $?
1

整数操作符

test命令除了有对字符串进行的操作符外,还有一些列针对整数的操作符。下列的文字描述只针对返回值为0时的情况:

int1 -eq int2 :int1等于int2
int1 -ne int2 :int1不等于int2
int1 -ge int2 :int1大于等于int2
int1 -gt int2 :int1大于int2
int1 -le int2 :int1小于等于int2
int1 -lt int2 :int1小于int2

如果在上述判断条件前加上逻辑非符号!,则表示对当前返回值取反。也就是说,如果该判断条件不满足时,返回值为0。比如:

edsionte@edsionte-laptop:~/shelltest$ [ 1 -ge 3 ]
edsionte@edsionte-laptop:~/shelltest$ echo $?
1
edsionte@edsionte-laptop:~/shelltest$ [ ! 1 -ge 3 ]
edsionte@edsionte-laptop:~/shelltest$ echo $?
0

我们还可以这么改进上文中的lu程序:

edsionte@edsionte-laptop:~/shelltest$ ./lu
usage: ./lu arg
edsionte@edsionte-laptop:~/shelltest$ cat lu
# look someone up in the info book
if [ $# -ne 1 ]
then
	echo "usage: ./lu arg"
else
	grep "^$1:" info
fi

逻辑操作符

上述所举的例子都是针对一条测试条件的,如果test命令的测试条件超过一条时,就应该使用逻辑操作符-a和-o。前者标示逻辑与,而这标示逻辑或。其使用方法可参考下例:

edsionte@edsionte-laptop:~/shelltest$ [ ! 1 -ge 3 -a 3 -ge 1 ]
edsionte@edsionte-laptop:~/shelltest$ echo $?
0
edsionte@edsionte-laptop:~/shelltest$ [ ! 1 -ge 3 -a 3 -le 1 ]
edsionte@edsionte-laptop:~/shelltest$ echo $?
1
edsionte@edsionte-laptop:~/shelltest$ [ ! 1 -ge 3 -o 3 -le 1 ]
edsionte@edsionte-laptop:~/shelltest$ echo $?
0

关于test命令更多的使用方法可以参考man手册。

shell编程中的参数传递

27 1 月, 2011 by edsionte 无评论 »

在shell程序中引入参数,shell程序就会灵活很多。本文首先简单介绍参数传递中的一些基本知识点,再通过一个通讯录的举例来加深对shell编程中参数传递的理解。

1. 参数的引用

当运行shell程序时,shell会自动将命令行中第一个参数保存在变量1中,第二个参数保存在变量2中,依次类推。因此,当需要在shell程序中使用这些参数时,便可以通过$1和$2这样的方法来引用。比如:

edsionte@edsionte-laptop:~/shelltest$ cat myargs
echo "\"$1\" \"$2\" was passed"
edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte wu
"edsionte" "wu" was passed
edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte
"edsionte" "" was passed
edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte wu me
"edsionte" "wu" was passed

通过上述举例可以看到,命令行中的第n个参数会自动传递给相应的特殊变量n。通过$n就可以在shell程序中对其进行引用;当引用未赋值的特殊变量时,其结果将会显示空。

2. #变量

每当shell程序运行时,特殊变量#中就会保存此次shell程序中键入的参数个数。比如:

echo "There are $# arguments passed"
echo "\"$1\" \"$2\" was passed"
edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte
There are 1 arguments passed
"edsionte" "" was passed

命令行中的参数是以空格作为间隔。因此,下面这种结果也很合理:

edsionte@edsionte-laptop:~/shelltest$ ./myargs "edsionte wu"
There are 1 arguments passed
"edsionte wu" "" was passed
edsionte@edsionte-laptop:~/shelltest$ name="edsionte wu"
edsionte@edsionte-laptop:~/shelltest$ ./myargs $name
There are 2 arguments passed
"edsionte" "wu" was passed

3. *变量

特殊变量*中会保存shell程序运行时用户键入的所有参数。在参数不确定或参数数目易变时,该变量就很有用。

edsionte@edsionte-laptop:~/shelltest$ cat myargs 
echo "There are $# arguments passed"
echo "\"$*\" was passed"
edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte wu is me
There are 4 arguments passed
"edsionte wu is me" was passed
edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte wu
There are 2 arguments passed
"edsionte wu" was passed

4. 通信录举例

查找用户

现在需要通过用户姓名从通信录info中查找一个用户的个人信息。我们通过编写shell程序lu来实现这个功能。最简单的程序为:

edsionte@edsionte-laptop:~/shelltest$ cat info
edsionte wu:male:xian:18717375182
sen wang:female:hanzhong:15678675545
ting li:male:guangzhou:15784859345
jedsionte:male:xian:13556567884
edison:male:hongkong:1384742488
yun zhang:female:beijing:18654737473
edsionte@edsionte-laptop:~/shelltest$ cat lu
# look someone up in the info book
grep $1 info
edsionte@edsionte-laptop:~/shelltest$ ./lu edsionte
edsionte wu:male:xian:18717375182
jedsionte:male:xian:13556567884

这个结果似乎并不令人满意,因为我们想找用户名为edsionte的用户。不过这个问题很好解决,我们可以这样改进程序:

edsionte@edsionte-laptop:~/shelltest$ cat lu
# look someone up in the info book
grep ^$1 info
edsionte@edsionte-laptop:~/shelltest$ ./lu edsionte
edsionte wu:male:xian:18717375182

如果我们想通过全名edsionte wu来查找用户信息,就应该用双引号将全名作为一个整体引入其中。这样看似很完美,可是结果却不尽人意:

edsionte@edsionte-laptop:~/shelltest$ ./lu "edsionte wu"
grep: wu: 没有那个文件或目录
info:edsionte wu:male:xian:18717375182

这是因为虽然edsionte wu作为一个参数传递给特殊变量1,但是shell将其替换后,grep命令并不认为edsionte wu是一个参数,而是将wu作为目标文件之一。为了避免这种情况,我们应该这样改进程序:

edsionte@edsionte-laptop:~/shelltest$ cat lu
# look someone up in the info book
grep "^$1" info
edsionte@edsionte-laptop:~/shelltest$ ./lu "edsionte wu"
edsionte wu:male:xian:18717375182

这样就可以满足我们要求了。但是,如果info中的信息如下所示,那么上述lu程序还是不算完美。比如:

edsionte@edsionte-laptop:~/shelltest$ cat info
edsionte wu:male:xian:18717375182
sen wang:female:hanzhong:15678675545
edsionte wuee:male:xian:18717375182
ting li:male:guangzhou:15784859345
jedsionte:male:xian:13556567884
edison:male:hongkong:1384742488
yun zhang:female:beijing:18654737473
edsionte@edsionte-laptop:~/shelltest$ ./lu "edsionte wu"
edsionte wu:male:xian:18717375182
edsionte wuee:male:xian:18717375182

因此,我们也应该在参数的尾部也做一些“手脚”,使得grep命令只匹配我们所传递的参数:

edsionte@edsionte-laptop:~/shelltest$ cat lu
# look someone up in the info book
grep "^$1:" info
edsionte@edsionte-laptop:~/shelltest$ ./lu "edsionte wu"
edsionte wu:male:xian:18717375182

至此,查找程序完成。

添加用户

当向通讯录中增添新用户信息时,我们必须再编写一个add程序。增加用户程序很简单:

edsionte@edsionte-laptop:~/shelltest$ cat add
# add someone to the info book
echo "$1:$2:$3:$4" >> info
edsionte@edsionte-laptop:~/shelltest$ ./add elva female taibei 1335676567
edsionte@edsionte-laptop:~/shelltest$ ./lu elva
elva:female:taibei:1335676567

>>使得新的信息会追加到原文件的末尾。在上述命令的基础上,我们还可以再增加按姓名排序的功能:

edsionte@edsionte-laptop:~/shelltest$ cat add
# add someone to the info book
echo "$1:$2:$3:$4" >> info
sort -o info info
edsionte@edsionte-laptop:~/shelltest$ cat info
edison:male:hongkong:1384742488
edsionte wuee:male:xian:18717375182
edsionte wu:male:xian:18717375182
elva:female:taibei:1335676567
jedsionte:male:xian:13556567884
sen wang:female:hanzhong:15678675545
ting li:male:guangzhou:15784859345
yun zhang:female:beijing:18654737473

添加程序结束。

删除用户

有了上述两个程序的基础,删除用户程序则变得容易很多。首先通过sed命令将完全匹配给定人名的用户信息从info中删除;因为sed命令并不改变info文件本身的内容,因此需要将sed的输出结果暂存至缓冲区;最后通过mv命令替换文件名即可。

edsionte@edsionte-laptop:~/shelltest$ cat del
# delete the given user from info
sed "/^$1:/d" info > /tmp/info
mv /tmp/info ./info
edsionte@edsionte-laptop:~/shelltest$ ./del elva
edsionte@edsionte-laptop:~/shelltest$ cat info
edison:male:hongkong:1384742488
edsionte wuee:male:xian:18717375182
edsionte wu:male:xian:18717375182
jedsionte:male:xian:13556567884
sen wang:female:hanzhong:15678675545
ting li:male:guangzhou:15784859345
yun zhang:female:beijing:18654737473

随着对shell编程的深入理解,上述通讯录程序还可以不断完善。

shell编程中的引用

24 1 月, 2011 by edsionte 无评论 »

shell编程语言中有四种引用符号,分别是单引号(”),双引号(“”),反单引号(“)和反斜杠。前三种符号必须成对出现来使用,而后者则单独使用。有时候我们需要shell将某些字符进行特殊解释,此时引用符号就派上了用场。

单引号

1.整体赋值

在对变量进行赋值时,使用单引号将中间有空格的字符引用后赋值给变量后,shell会将这些字符看作成一个整体来处理。比如,我们需要在name文件中查找edsionte wu这个姓名:

edsionte@edsionte-desktop:~/shelltest$ cat name
edsionte
zhanyu
miao
edsionte wu
edsionteli
edsionte@edsionte-desktop:~/shelltest$ grep edsionte wu name
grep: wu: 没有那个文件或目录
name:edsionte
name:edsionte wu
name:edsionteli

此时grep命令产生了错误信息。由于edsionte和wu字符之间有空格,grep将edsionte视为要查找的字符,而wu和name都是所要查找的文件。如果我们将edsionte和wu放入单引号内,就可以正确得到结果:

edsionte@edsionte-desktop:~/shelltest$ grep 'edsionte wu' name
edsionte wu

通过使用单引号,shell从上面的那条命令中提取到edsionte wu和name两个参数,再将这两个参数传递给grep命令。

2.保留字符

使用单引号将字符引用后,shell会原封不动的保留单引号内的字符,比如:

edsionte@edsionte-desktop:~/shelltest$ echo edsionte              wu
edsionte wu
edsionte@edsionte-desktop:~/shelltest$ echo 'edsionte              wu'
edsionte              wu

不使用单引号时,shell会将字符之间的多个空格缩减至一个;如果使用了单引号,那么shell会原封不动将单引号中的内容提取出来,送至echo命令。 同样,由于单引号原封不动的特性,处于单引号内部的特殊字符不会被shell解释。比如:

edsionte@edsionte-desktop:~/shelltest$ ls
gender  name  number
edsionte@edsionte-desktop:~/shelltest$ echo *
gender name number
edsionte@edsionte-desktop:~/shelltest$ echo '*'
*

可以看到,特殊字符*并不会被单引号所解释。接下来的这个例子会让你更深入的理解上述两个功能。比如:

edsionte@edsionte-desktop:~/shelltest$ files='I have these files: *'
edsionte@edsionte-desktop:~/shelltest$ echo $files
I have these files: gender name number

可能你会有疑问:处于单引号内的*为什么会被shell解释呢?如果你理解了这里的单引号所起的作用就回消除上面的疑惑。对于echo $files命令来说,shell会先将$file替换为I have these files: *,也就是说这里的单引号是为了将上述字符整体赋值给files变量;然后shell会将*替换为当前目录下的所有文件名;最后将I have these files: gender name number作为一个整体传给echo命令。

双引号

双引号和单引号的功能几乎相同,只不过双引号对个别几个特殊字符会做解释,而不像单引号那样完全忽略所有特殊字符。这几个特殊字符为:美元符号($),反引号(“),反斜杠(/)。比如:

edsionte@edsionte-laptop:~/shelltest$ ls
info  name  nf  status  test  whos
edsionte@edsionte-laptop:~/shelltest$ x=*
edsionte@edsionte-laptop:~/shelltest$ echo $x
info name nf status test whos
edsionte@edsionte-laptop:~/shelltest$ echo '$x'
$x
edsionte@edsionte-laptop:~/shelltest$ echo "$x"
*

可以看到,shell对位于双引号内的$进行了解释,也就是将其解释为对x变量的引用。除此之外,双引号和单引号并无太大差异。比如:

edsionte@edsionte-laptop:~/shelltest$ x="edsionte    wu"
edsionte@edsionte-laptop:~/shelltest$ echo $x
edsionte wu
edsionte@edsionte-laptop:~/shelltest$ echo "$x"
edsionte    wu
edsionte@edsionte-laptop:~/shelltest$ echo '$x'
$x

对于第一条的赋值语句,不管使用单引号还是双引号,效果是一样的,都是将edsionte wu作为一个整体赋值给变量x。

反引号

在命令A中使用反引号的目的并不是希望shell保留某些特殊字符的本意,而是将其他的命令B包含起来,并把命令B的输出插入到命令B所在的位置。其格式为:
cmdA `cmdB`

比如通过反引号的引用在echo命令中使用date命令:
edsionte@edsionte-desktop:~/shelltest$ echo 'Now is `date`'
Now is `date`
edsionte@edsionte-desktop:~/shelltest$ echo "Now is `date`"
Now is 2011年 01月 25日 星期二 16:48:40 CST

由于单引号对任何字符都不作特殊解释,因此反引号在单引号中并不起作用。但是在双引号中,反引号中的date命令被shell解释了。
由于双引号

反斜杠

1.消除特殊含义

如果在一些特殊字符前面加上反斜杠,则会消除这些字符的特殊含义。因此\c的功效相当于’c’。比如:

edsionte@edsionte-desktop:~/shelltest$ x=*
edsionte@edsionte-desktop:~/shelltest$ echo $x
gender name number
edsionte@edsionte-desktop:~/shelltest$ echo \$x
$x

可以看到,在$前面加入反斜杠可以去除$的引用含义而将$本身显示出来。

2.续行

当反斜杠位于一行的最后一个字符时,它会起到续行的作用。比如:

edsionte@edsionte-desktop:~/shelltest$ file=edsion\
> te
edsionte@edsionte-desktop:~/shelltest$ echo $file
edsionte

使用反斜杠进行续行后,反斜杠前后的字符之间并没有分隔符。

3.在双引号中使用 反斜杠

如果我们希望shell保留双引号中的特殊字符(即$、“和\)的含义,那么反斜杠就派上了用场。比如:

edsionte@edsionte-desktop:~/shelltest$ x=5
edsionte@edsionte-desktop:~/shelltest$ echo "The value of \$x is $x"
The value of $x is 5

end

cut命令和paste命令

19 1 月, 2011 by edsionte 无评论 »
cut命令

顾名思义,cut命令就是从文本文件或从某个命令的输出数据中裁剪(析取)出想要的数据域。cut命令一般使用的方式为:

cut -cchars file

其中,-cchar中的-c为cut命令的常用选项,表示从file文件的每一行中都cut出chars这段文字。。chars的取值较为灵活,分为以下几种情况。

cut -c5 file:析取file文件每行的第5个字符;

cut -c5,7 file:析取file文件每行第5和第7个字符;

cut -c6-8 file:析取file文件每行第6到第8个字符;

cut -c6- file:析取file文件每行第6个到行尾之间的字符;

cut -c-3 file:析取file文件每行行首到第三个字符之间的字符;

如果cut命令中未指定file,则将标准输入作为cut命令的析取对象。比如:

edsionte@edsionte-desktop:~$ ls -l
总用量 1680
drwx------  2 edsionte edsionte   4096 2011-01-10 20:38 android_code
-rwxrwxrwx  1 edsionte edsionte   7138 2011-01-13 08:42 a.out
drwxr-xr-x  2 edsionte edsionte   4096 2011-01-16 21:46 assembly
drwxr-xr-x  2 edsionte edsionte   4096 2011-01-11 09:58 bin
drwx------ 24 edsionte edsionte   4096 2011-01-17 11:35 code
edsionte@edsionte-desktop:~$ ls -l | cut -c1-9
总用量
drwx-----
-rwxrwxrw
drwxr-xr-
drwxr-xr-
drwx-----

上述cut命令中,将ls命令的输出作为cut命令的输入。产生的结果是析取出每列数据的第1到第9个字符,也既是每个文件的访问权限。下面的例子通过逗号隔开两个数值列表,分别析取出文件访问权限和文件名。

edsionte@edsionte-desktop:~$ ls -l
总用量 1680
drwx------  2 edsionte edsionte   4096 2011-01-10 20:38 android_code
-rwxrwxrwx  1 edsionte edsionte   7138 2011-01-13 08:42 a.out
drwxr-xr-x  2 edsionte edsionte   4096 2011-01-16 21:46 assembly
drwxr-xr-x  2 edsionte edsionte   4096 2011-01-11 09:58 bin
drwx------ 24 edsionte edsionte   4096 2011-01-17 11:35 code
edsionte@edsionte-desktop:~$ ls -l | cut -c1-9,56-
总用量
drwx----- android_code
-rwxrwxrw a.out
drwxr-xr- assembly
drwxr-xr- bin
drwx----- code

-d和-f选项

通过上述的例子可以看到,如果单纯使用-c选项,则必须很清楚所要解析字符在每行中的位置;另外,-c选项适用从格式固定的文件或命令输出中解析出所需要的字符。如果文件数据的组织格式不固定,则很难使用-c选项从每行中都解析出所需的字符。

比如我们常常会遇到这样的个人信息,包含姓名,性别,城市,爱好,电话:

edsionte:male:xian:music:18717375182
zhyun:famle:beijing:basketball:18654737473
liting:male:zhangjiajie:tableball:15784859345

现在如果要解析出姓名,使用-c选项则不可能做到。不过该文件有一个特点,每行信息中的每个字段都使用分号隔开,此时我们就可以使用-f和-d选项:

cut -ddchar -ffields file

dchar表示我们析取字段时所依据的分隔符;fields标示我们所要析取的字段序号,可用逗号隔开多个字段序号。对于上面的例子,我们可以这么做:

edsionte@edsionte-laptop:~/shelltest$ cut -d: -f1 info
edsionte
zhyun
liting

cut命令将制表符(\t)作为默认的字段分隔符,如果某个文件用制表符作为每行各个字段的分隔符,则使用cut -ffield file即可析取相应字段。

paste命令

与cut命令相反,paste命令可以将多个文件对应行的数据连接在一起,数据之间使用制表符隔开。合并后的结果默认在标准输出中输出。该命令基本使用方法为:

paste files

比如将下面的name和gender合并在一起:

edsionte@edsionte-desktop:~/shelltest$ cat name
edsionte
wangsen
zhanyu
edsionte@edsionte-desktop:~/shelltest$ cat gender
m
m
f
f
m
edsionte@edsionte-desktop:~/shelltest$ paste name gender
edsionte	m
wangsen	m
zhanyu	f
	f
	m

可以看到,由于name文件中只有三行数据,因此gender文件中最后两行和空字符合并在一起。

-d选项

通过-d选项可以指定任意分隔符来隔开不同文件每行的内容,基本使用方法为:

paste -dchars files

dchar可以取多个分隔符,每个分隔符依次隔开files中每个文件每行的数据。比如:

edsionte@edsionte-desktop:~/shelltest$ paste -d~, name gender number
edsionte~m,123
wangsen~m,456
zhanyu~f,789
~f,
~m,

从这个例子也可以看出,name和number文件的第4和第5行的数据均为空。

-s选项

通过这个选项可以将一个文件每行的数据都合并在一起。比如:

edsionte@edsionte-desktop:~/shelltest$ ls
file1  file3  file5  file7  gender  number
file2  file4  file6  file8  name
edsionte@edsionte-desktop:~/shelltest$ ls | paste -s -d@
file1@file2@file3@file4@file5@file6@file7@file8@gender@name@number

对于上述两个命令,使用-d选项时最好将分隔符放在单引号中。原因很简单,比如:

edsionte@edsionte-desktop:~/shelltest$ ls | paste -s -d;
paste:选项需要一个参数 -- d
请尝试执行"paste --help"来获取更多信息。

原因是shell并没有将;作为分隔符,而是认为它是paste命令的结束标志。这里的原因跟转义字符差不多,因为此时我们需要使用;的本意。加上单引号即可成功执行上述命令:

edsionte@edsionte-desktop:~/shelltest$ ls | paste -s -d';'
file1;file2;file3;file4;file5;file6;file7;file8;gender;name;number

目录文件的访问权限

17 1 月, 2011 by edsionte 无评论 »

目录的访问权限

在linux当中,文件分为多种类型。比如普通文件,目录文件和符号链接文件等。我们通常所说的“文件”则默认为普通文件,也就是指文本文件和二进制文件(关于文件的分类描述,可参看这里)。

每一类文件还有相应的访问权限。对于一个文件而言,所谓的访问权限是指文件访问者是否对该文件具有读、写或执行的权利。另外,linux是一个多用户的操作系统,它将用户分为三种:用户(u,即文件所有者),用户所在组(g),其他用户(o)。因此,对于不同身份的用户,也就应当对一个文件有不同的访问权限。所以,每个文件有9个访问权限。

对于目录文件的权限,他和普通文件稍有不同;

读:可以读取该目录,从中获得该目录中所有文件名,但不能读取到每个文件的状态;
执行:可以对该目录进行搜索,也就是通过该目录可以搜索其内的特定文件名;
写:可以在该目录下新建或删除文件,但是首先必须对该目录拥有执行权限。如果该目录没有执行权限就不能对该目录下的文件进行搜索,新建或删除文件也就无从谈起;

测试

对于目录的访问权限,从文字描述的角度并不能理解的很清楚。因此,通过不断的测试才能理解这些访问权限对目录的作用效果。我们假设在edsionte主目录下有一个dirtest目录,其基本信息如下:

edsionte@edsionte-desktop:~$ ls -ld dirtest/
drwxr-xr-x 4 edsionte edsionte 4096 2011-01-17 11:06 dirtest/
edsionte@edsionte-desktop:~$ ls -l dirtest/
总用量 16
drwxr-xr-x 3 edsionte edsionte 4096 2011-01-15 16:10 cdev
-rw-r--r-- 1 edsionte edsionte  975 2010-10-17 22:06 pms.c
drwxr-xr-x 2 edsionte edsionte 4096 2011-01-13 20:49 shell
-rw-r--r-- 1 edsionte edsionte   19 2011-01-13 21:08 test.c

接下来的测试都是以edsionte用户身份对这个目录进行各种命令测试的,具体如下:

1.通过ls dirtest命令,可参看该目录下的文件名。因为这个目录具有读权限;

edsionte@edsionte-desktop:~$ ls dirtest/
cdev  pms.c  shell  test.c

2.先使得dirtest没有执行,再执行ls命令。可以看到,虽然可以读到每个文件名,但是每个文件的属性确无法获得;

edsionte@edsionte-desktop:~$ chmod a-x dirtest/
edsionte@edsionte-desktop:~$ ls dirtest/ -l
ls: 无法访问dirtest/shell: 权限不够
ls: 无法访问dirtest/test.c: 权限不够
ls: 无法访问dirtest/pms.c: 权限不够
ls: 无法访问dirtest/cdev: 权限不够
总用量 0
d????????? ? ? ? ?                ? cdev
-????????? ? ? ? ?                ? pms.c
d????????? ? ? ? ?                ? shell
-????????? ? ? ? ?                ? test.c

3.由于没有执行权限,无法搜索判断dirtest目录下是否已存在newfile.c文件,因此无法完成touch命令,即便该目录具有写权限;

edsionte@edsionte-desktop:~$ ls -ld dirtest/
drw-r--r-- 4 edsionte edsionte 4096 2011-01-17 11:06 dirtest/
edsionte@edsionte-desktop:~$ touch dirtest/newfile.c
touch: 无法创建"dirtest/newfile.c": 权限不够

对于目录文件,也是如此:

edsionte@edsionte-desktop:~$ chmod a-x dirtest/
edsionte@edsionte-desktop:~$ mkdir ./dirtest/newdir
mkdir: 无法创建目录"./dirtest/newdir": 权限不够

4.对该目录加上执行权限后,2和3中所遇到的问题都可以解决:

edsionte@edsionte-desktop:~$ chmod a+x dirtest/
edsionte@edsionte-desktop:~$ touch dirtest/newfile.c
edsionte@edsionte-desktop:~$ ls -l dirtest/
总用量 16
drwxr-xr-x 3 edsionte edsionte 4096 2011-01-15 16:10 cdev
-rw-r--r-- 1 edsionte edsionte    0 2011-01-17 11:36 newfile.c
-rw-r--r-- 1 edsionte edsionte  975 2010-10-17 22:06 pms.c
drwxr-xr-x 2 edsionte edsionte 4096 2011-01-13 20:49 shell
-rw-r--r-- 1 edsionte edsionte   19 2011-01-13 21:08 test.c

5.继续使得dirtest没有执行权限,由于不能读取dirtest下的目录cdev,也就更不能读取cdev目录下的文件,即便cdev具有可读可执行权限;

edsionte@edsionte-desktop:~$ ls -ld dirtest/cdev/
drwxr-xr-x 3 edsionte edsionte 4096 2011-01-15 16:10 dirtest/cdev/
edsionte@edsionte-desktop:~$ chmod a-x dirtest/
edsionte@edsionte-desktop:~$ ls -ld dirtest/cdev/
ls: 无法访问dirtest/cdev/: 权限不够
edsionte@edsionte-desktop:~$ ls -l dirtest/cdev/
ls: 无法访问dirtest/cdev/: 权限不够

6.如果dirtest有执行权限却没有写权限,则不能创建新文件。这一点很好理解;

edsionte@edsionte-desktop:~$ ls -ld dirtest/
dr-xr-xr-x 4 edsionte edsionte 4096 2011-01-17 11:36 dirtest/
edsionte@edsionte-desktop:~$ mkdir ./dirtest/newdir
mkdir: 无法创建目录"./dirtest/newdir": 权限不够

7.如果dirtest有写权限却没有执行权限,则不能在该目录下删除文件;

edsionte@edsionte-desktop:~$ chmod a-x dirtest/
edsionte@edsionte-desktop:~$ ls -ld dirtest/
drw-rw-rw- 4 edsionte edsionte 4096 2011-01-17 11:36 dirtest/
edsionte@edsionte-desktop:~$ rm ./dirtest/newfile.c
rm: 无法删除"./dirtest/newfile.c": 权限不够

8.如果dirtest目录有可写权限没有可执行权限,虽然可以打开该目录下的文件test.c,但是对其修改后不能保存;

edsionte@edsionte-desktop:~$ ls dirtest/
cdev  newfile.c  pms.c  shell  test.c
edsionte@edsionte-desktop:~$ chmod a-x dirtest/
edsionte@edsionte-desktop:~$ vim ./dirtest/test.c

9.如果要修改dirtest目录下的文件test.c,对于dirtest目录而言,必须具备执行权限;而该目录的写权限则与test.c的修改无关;

通过上面的测试,我们可以得出下面的结论:

1.对一个目录进行读操作,即指读该目录下的文件名;

2.对一个目录的“写”包括在该目录下删除、新建文件;更重要的是,只有该目录有可执行权限时,写操作才可以进行,否则,不能获取该目录下除文件名之外的任何文件状态信息;

3.如果在一次文件操作中,只要涉及到对目录的搜索,则该目录必须具备执行权限,否则写权限就无法进行;

一个目录的执行权限可以用下面的比喻来解释。一个目录就好像是一道门,该目录中的文件就是你想要的珍宝。并且,该门之后可能还会有其他门的存在。目录的可执行权限相当于打开这把门的钥匙,只有持有这把钥匙,你才能打开这扇目录之门。打开门后,你可能会拿走一些宝石(删除文件),或者放入一些宝石(新建文件)等。否则,你只能隔门相望门后的宝石了(只能读取文件名)。

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key