高级Bash脚本编程指南(7):文件测试操作符
2013-05-06 14:08
141 查看
高级Bash脚本编程指南(7):文件测试操作符
成于坚持,败于止步
如果下面的条件成立将会返回真.
-e
文件存在
-a
文件存在,这个选项的效果与-e相同. 但是它已经被"弃用"了, 并且不鼓励使用.
-f
表示这个文件是一个一般文件(并不是目录或者设备文件)
-s
文件大小不为零
-d
表示这是一个目录
-b
表示这是一个块设备(软盘, 光驱, 等等.)
-c
表示这是一个字符设备(键盘, modem, 声卡, 等等.)
-p
这个文件是一个管道
-h
这是一个符号链接
-L
这是一个符号链接
-S
表示这是一个socket
-t
文件(描述符)被关联到一个终端设备上,这个测试选项一般被用来检测脚本中的stdin([ -t 0 ]) 或者stdout([ -t 1 ])是否来自于一个终端.
-r
文件是否具有可读权限(指的是正在运行这个测试命令的用户是否具有读权限)
-w
文件是否具有可写权限(指的是正在运行这个测试命令的用户是否具有写权限)
-x
文件是否具有可执行权限(指的是正在运行这个测试命令的用户是否具有可执行权限)
-g
set-group-id(sgid)标记被设置到文件或目录上,如果目录具有sgid标记的话, 那么在这个目录下所创建的文件将属于拥有这个目录的用户组, 而不必是创建这个文件的用户组. 这个特性对于在一个工作组中共享目录非常有用.
-u
set-user-id (suid)标记被设置到文件上,如果一个root用户所拥有的二进制可执行文件设置了set-user-id标记位的话, 那么普通用户也会以root权限来运行这个文件. [1] 这对于需要访问系统硬件的执行程序(比如pppd和cdrecord)非常有用. 如果没有suid标志的话, 这些二进制执行程序是不能够被非root用户调用的.对于设置了suid标志的文件, 在它的权限列中将会以s表示.其实这个权限在最初说文件权限的文章中已经说过了,比较特殊的一种权限
-k
设置粘贴位,对于"粘贴位"的一般了解, save-text-mode标志是一个文件权限的特殊类型. 如果文件设置了这个标志, 那么这个文件将会被保存到缓存中, 这样可以提高访问速度. [2] 粘贴位如果设置在目录中, 那么它将限制写权限. 对于设置了粘贴位的文件或目录, 在它们的权限标记列中将会显示t.
-O
判断你是否是文件的拥有者
-G
文件的group-id是否与你的相同
-N
从文件上一次被读取到现在为止, 文件是否被修改过
f1 -nt f2
文件f1比文件f2新
f1 -ot f2
文件f1比文件f2旧
f1 -ef f2
文件f1和文件f2是相同文件的硬链接
!
"非" -- 反转上边所有测试的结果(如果没给出条件, 那么返回真).
这里只是先把一个实例贴在这里,暂且不做任何分析,因为现在去分析这个程序还有点为时尚早:
其他比较操作符
二元比较操作符用来比较两个变量或数字. 注意整数比较与字符串比较的区别.
整数比较
-eq
等于
if [ "$a" -eq "$b" ]
-ne
不等于
if [ "$a" -ne "$b" ]
-gt
大于
if [ "$a" -gt "$b" ]
-ge
大于等于
if [ "$a" -ge "$b" ]
-lt
小于
if [ "$a" -lt "$b" ]
-le
小于等于
if [ "$a" -le "$b" ]
<
小于(在双括号中使用)
(("$a" < "$b"))
<=
小于等于(在双括号中使用)
(("$a" <= "$b"))
>
大于(在双括号中使用)
(("$a" > "$b"))
>=
大于等于(在双括号中使用)
(("$a" >= "$b"))
字符串比较
=
等于
if [ "$a" = "$b" ]
==
等于
if [ "$a" == "$b" ]
与=等价,不过,==比较操作符在双中括号对和单中括号对中的行为是不同的.我们看看实例,理解一下:
1.只要前两个字符为“ab”就为true
2.意思是变量a只有是“ab*”这三个字符时跟后面比较的字符完全一致才为true
3.就是完全比配的情况,返回肯定是true
4.和第二个是一样的
5.这个就是比较特殊的情况,我的理解是在单【】中文字扩展匹配和单词分割有效,所以不能采用这么模糊比较的方法,模糊比较必须使用双【【】】
!=
不等号
if [ "$a" != "$b" ]
这个操作符将在[[ ... ]]结构中使用模式匹配.
<
小于, 按照ASCII字符进行排序
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]
注意"<"使用在[ ]结构中的时候需要被转义.
>
大于, 按照ASCII字符进行排序
if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]
注意">"使用在[ ]结构中的时候需要被转义.
-z
字符串为"null", 意思就是字符串长度为零
-n
字符串不为"null".当-n使用在中括号中进行条件测试的时候, 必须要把字符串用双引号引用起来. 如果采用了未引用的字符串来使用! -z, 甚至是在条件测试中括号中只使用未引用的字符串的话, 一般也是可以工作的, 然而, 这是一种不安全的习惯. 习惯于使用引用的测试字符串才是正路.
实例一
针对判断字符串是否为空,还是要特别说一下吧,比较特殊:
结果:
string1和string2同是未定义的string,为什么string1判断是非null,而string2判断就是null,对string1的判断明显是错误的,对string的操作加上“”是很有必要的,sting5和string6的比较同样说明了这一点
继续看一个实例:
上面几个判断条件使用方法是重点关注的地方:
1.判断参数个数为0退出
2.先判断FILENAME是否为文件,再取反,即不是文件或找不到文件退出
3.判断文件后缀名是不是“.txt”,不是则退出
结果:
最后提一下逻辑判断方法
-a
逻辑与
exp1 -a exp2 如果表达式exp1和exp2都为真的话, 那么结果为真.
-o
逻辑或
exp1 -o exp2 如果表达式exp1和exp2中至少有一个为真的话, 那么结果为真.
这与Bash中的比较操作符&&和||非常相像, 但是这个两个操作符是用在双中括号结构中的.
比如用在【【】】中 [[ condition1 && condition2 ]]
-o和-a操作符一般都是和test命令或者是单中括号结构一起使用的, if [ "$exp1" -a "$exp2" ]
先到这里了,O(∩_∩)O~
我的专栏地址:http://blog.csdn.net/column/details/shell-daily-study.html
待续。。。。。
成于坚持,败于止步
如果下面的条件成立将会返回真.
-e
文件存在
-a
文件存在,这个选项的效果与-e相同. 但是它已经被"弃用"了, 并且不鼓励使用.
-f
表示这个文件是一个一般文件(并不是目录或者设备文件)
-s
文件大小不为零
-d
表示这是一个目录
-b
表示这是一个块设备(软盘, 光驱, 等等.)
-c
表示这是一个字符设备(键盘, modem, 声卡, 等等.)
-p
这个文件是一个管道
-h
这是一个符号链接
-L
这是一个符号链接
-S
表示这是一个socket
-t
文件(描述符)被关联到一个终端设备上,这个测试选项一般被用来检测脚本中的stdin([ -t 0 ]) 或者stdout([ -t 1 ])是否来自于一个终端.
-r
文件是否具有可读权限(指的是正在运行这个测试命令的用户是否具有读权限)
-w
文件是否具有可写权限(指的是正在运行这个测试命令的用户是否具有写权限)
-x
文件是否具有可执行权限(指的是正在运行这个测试命令的用户是否具有可执行权限)
-g
set-group-id(sgid)标记被设置到文件或目录上,如果目录具有sgid标记的话, 那么在这个目录下所创建的文件将属于拥有这个目录的用户组, 而不必是创建这个文件的用户组. 这个特性对于在一个工作组中共享目录非常有用.
-u
set-user-id (suid)标记被设置到文件上,如果一个root用户所拥有的二进制可执行文件设置了set-user-id标记位的话, 那么普通用户也会以root权限来运行这个文件. [1] 这对于需要访问系统硬件的执行程序(比如pppd和cdrecord)非常有用. 如果没有suid标志的话, 这些二进制执行程序是不能够被非root用户调用的.对于设置了suid标志的文件, 在它的权限列中将会以s表示.其实这个权限在最初说文件权限的文章中已经说过了,比较特殊的一种权限
-k
设置粘贴位,对于"粘贴位"的一般了解, save-text-mode标志是一个文件权限的特殊类型. 如果文件设置了这个标志, 那么这个文件将会被保存到缓存中, 这样可以提高访问速度. [2] 粘贴位如果设置在目录中, 那么它将限制写权限. 对于设置了粘贴位的文件或目录, 在它们的权限标记列中将会显示t.
-O
判断你是否是文件的拥有者
-G
文件的group-id是否与你的相同
-N
从文件上一次被读取到现在为止, 文件是否被修改过
f1 -nt f2
文件f1比文件f2新
f1 -ot f2
文件f1比文件f2旧
f1 -ef f2
文件f1和文件f2是相同文件的硬链接
!
"非" -- 反转上边所有测试的结果(如果没给出条件, 那么返回真).
这里只是先把一个实例贴在这里,暂且不做任何分析,因为现在去分析这个程序还有点为时尚早:
#!/bin/bash #一个纯粹的shell脚本用来找出那些断掉的符号链接文件并且输出它们所指向的文件. #以便于它们可以把输出提供给xargs来进行处理 :) #比如. xxx.sh /somedir /someotherdir|xargs rm #下边的方法, 不管怎么说, 都是一种更好的办法: #find "somedir" -type l -print0|\ #xargs -r0 file|\ #grep "broken symbolic"| #sed -e 's/^\|: *broken symbolic.*$/"/g' #但这不是一个纯粹的bash脚本, 最起码现在不是. #注意: 谨防在/proc文件系统和任何死循环链接中使用! #如果没有参数被传递到脚本中, 那么就使用 #当前目录. 否则就是用传递进来的参数作为目录 #来搜索. [ $# -eq 0 ] && directorys=`pwd` || directorys=$@ #编写函数linkchk用来检查传递进来的目录或文件是否是链接, #并判断这些文件或目录是否存在. 然后打印它们所指向的文件. #如果传递进来的元素包含子目录, #那么把子目录也放到linkcheck函数中处理, 这样就达到了递归的目的. linkchk () { for element in $1/*; do [ -h "$element" -a ! -e "$element" ] && echo \"$element\" [ -d "$element" ] && linkchk $element # 当然, '-h'用来测试符号链接, '-d'用来测试目录. done } #把每个传递到脚本的参数都送到linkchk函数中进行处理, #检查是否有可用目录. 如果没有, 那么就打印错误消息和 #使用信息. for directory in $directorys; do if [ -d $directory ] then linkchk $directory else echo "$directory is not a directory" echo "Usage: $0 dir1 dir2 ..." fi done exit 0
其他比较操作符
二元比较操作符用来比较两个变量或数字. 注意整数比较与字符串比较的区别.
整数比较
-eq
等于
if [ "$a" -eq "$b" ]
-ne
不等于
if [ "$a" -ne "$b" ]
-gt
大于
if [ "$a" -gt "$b" ]
-ge
大于等于
if [ "$a" -ge "$b" ]
-lt
小于
if [ "$a" -lt "$b" ]
-le
小于等于
if [ "$a" -le "$b" ]
<
小于(在双括号中使用)
(("$a" < "$b"))
<=
小于等于(在双括号中使用)
(("$a" <= "$b"))
>
大于(在双括号中使用)
(("$a" > "$b"))
>=
大于等于(在双括号中使用)
(("$a" >= "$b"))
字符串比较
=
等于
if [ "$a" = "$b" ]
==
等于
if [ "$a" == "$b" ]
与=等价,不过,==比较操作符在双中括号对和单中括号对中的行为是不同的.我们看看实例,理解一下:
#!/bin/bash a=abcdef if [[ $a == ab* ]] then echo "result1: true" else echo "result1: false" fi if [[ $a == "ab*" ]] then echo "result2: true" else echo "result2: false" fi if [ $a == abcdef ] then echo "result3: true" else echo "result3: false" fi if [ $a == "ab*" ] then echo "result4: true" else echo "result4: false" fi if [ $a == ab* ] then echo "result5: true" else echo "result5: false" fi exit 0结果:
root@ubuntu:~/resource/shell-study/0427-2013# ./test2 result1: true result2: false result3: true result4: false result5: false分析:
1.只要前两个字符为“ab”就为true
2.意思是变量a只有是“ab*”这三个字符时跟后面比较的字符完全一致才为true
3.就是完全比配的情况,返回肯定是true
4.和第二个是一样的
5.这个就是比较特殊的情况,我的理解是在单【】中文字扩展匹配和单词分割有效,所以不能采用这么模糊比较的方法,模糊比较必须使用双【【】】
!=
不等号
if [ "$a" != "$b" ]
这个操作符将在[[ ... ]]结构中使用模式匹配.
<
小于, 按照ASCII字符进行排序
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]
注意"<"使用在[ ]结构中的时候需要被转义.
>
大于, 按照ASCII字符进行排序
if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]
注意">"使用在[ ]结构中的时候需要被转义.
-z
字符串为"null", 意思就是字符串长度为零
-n
字符串不为"null".当-n使用在中括号中进行条件测试的时候, 必须要把字符串用双引号引用起来. 如果采用了未引用的字符串来使用! -z, 甚至是在条件测试中括号中只使用未引用的字符串的话, 一般也是可以工作的, 然而, 这是一种不安全的习惯. 习惯于使用引用的测试字符串才是正路.
实例一
#!/bin/bash a=4 b=5 # 这里的"a"和"b"既可以被认为是整型也可被认为是字符串. # 这里在算术比较与字符串比较之间是容易让人产生混淆, 因为Bash变量并不是强类型的. # Bash允许对于变量进行整形操作与比较操作.但前提是变量中只能包含数字字符. # 不管怎么样, 还是要小心. if [ "$a" -ne "$b" ] then echo "$a is not equal to $b" echo "(arithmetic comparison)" fi if [ "$a" != "$b" ] then echo "str($a) is not equal to str($b)." echo "(string comparison)" # "4" != "5" # ASCII 52 != ASCII 53 fi exit 0结果:
root@ubuntu:~/resource/shell-study/0427-2013# ./test3 4 is not equal to 5 (arithmetic comparison) str(4) is not equal to str(5). (string comparison)-ne比较的是两个整数,!=比较的是两个字符串
针对判断字符串是否为空,还是要特别说一下吧,比较特殊:
#!/bin/bash # -n if [ -n $string1 ];then echo "String \"string1\" is not null." else echo "String \"string1\" is null." fi #This is the best way if [ -n "$string2" ];then echo "String \"string2\" is not null." else echo "String \"string2\" is null." fi if [ $string3 ];then echo "String \"string3\" is not null." else echo "String \"string3\" is null." fi string4=initialize if [ $string4 ];then echo "String \"string4\" is not null." else echo "String \"string4\" is null." fi string5="a = b" if [ $string5 ];then echo "String \"string5\" is not null." else echo "String \"string5\" is null." fi string6="a = b" if [ "$string6" ];then echo "String \"string6\" is not null." else echo "String \"string6\" is null." fi exit 0
结果:
root@ubuntu:~/resource/shell-study/0506-2013# ./test1.sh String "string1" is not null. String "string2" is null. String "string3" is null. String "string4" is not null. String "string5" is null. String "string6" is not null.分析:
string1和string2同是未定义的string,为什么string1判断是非null,而string2判断就是null,对string1的判断明显是错误的,对string的操作加上“”是很有必要的,sting5和string6的比较同样说明了这一点
继续看一个实例:
#!/bin/bash NOARGS=65 NOTFOUND=66 NOTTXT=67 if [ $# -eq 0 ];then echo "Usage: `basename $0` no filename!" >&2 exit $NOARGS fi FILENAME=$1 if [ ! -f "$FILENAME" ];then echo "File $FILENAME not found!" >&2 exit $NOTFOUND fi if [ ${FILENAME##*.} != "txt" ];then echo "File $1 is not a txt file!" >&2 exit $NOTTXT fi cat $1 | more exit 0
上面几个判断条件使用方法是重点关注的地方:
1.判断参数个数为0退出
2.先判断FILENAME是否为文件,再取反,即不是文件或找不到文件退出
3.判断文件后缀名是不是“.txt”,不是则退出
结果:
root@ubuntu:~/resource/shell-study/0506-2013# ls file.txt file.zip test1.sh test2.sh root@ubuntu:~/resource/shell-study/0506-2013# ./test2.sh Usage: test2.sh no filename! root@ubuntu:~/resource/shell-study/0506-2013# ./test2.sh file File file not found! root@ubuntu:~/resource/shell-study/0506-2013# ./test2.sh file.zip File file.zip is not a txt file! root@ubuntu:~/resource/shell-study/0506-2013# ./test2.sh file.txt total 7476 -rwxr-xr-x 1 root root 818232 2010-04-18 18:51 bash -rwxr-xr-x 1 root root 30200 2010-02-08 02:54 bunzip2 -rwxr-xr-x 1 root root 1269432 2010-04-22 13:04 busybox -rwxr-xr-x 1 root root 30200 2010-02-08 02:54 bzcat lrwxrwxrwx 1 root root 6 2012-11-30 05:12 bzcmp -> bzdiff -rwxr-xr-x 1 root root 2140 2010-02-08 02:54 bzdiff lrwxrwxrwx 1 root root 6 2012-11-30 05:12 bzegrep -> bzgrep -rwxr-xr-x 1 root root 4874 2010-02-08 02:54 bzexe lrwxrwxrwx 1 root root 6 2012-11-30 05:12 bzfgrep -> bzgrep -rwxr-xr-x 1 root root 3642 2010-02-08 02:54 bzgrep -rwxr-xr-x 1 root root 30200 2010-02-08 02:54 bzip2 -rwxr-xr-x 1 root root 9580 2010-02-08 02:54 bzip2recover lrwxrwxrwx 1 root root 6 2012-11-30 05:12 bzless -> bzmore -rwxr-xr-x 1 root root 1297 2010-02-08 02:54 bzmore -rwxr-xr-x 1 root root 50820 2010-03-04 19:29 cat -rwxr-xr-x 1 root root 54956 2010-03-04 19:29 chgrp -rwxr-xr-x 1 root root 50836 2010-03-04 19:29 chmod -rwxr-xr-x 1 root root 54964 2010-03-04 19:29 chown -rwxr-xr-x 1 root root 9632 2010-03-11 23:05 chvt -rwxr-xr-x 1 root root 96140 2010-03-04 19:29 cp -rwxr-xr-x 1 root root 114448 2010-03-04 19:25 cpio -rwxr-xr-x 1 root root 83888 2010-04-01 12:22 dash -rwxr-xr-x 1 root root 63128 2010-03-04 19:29 date -rwxr-xr-x 1 root root 9672 2010-03-30 08:07 dbus-cleanup-sockets -rwxr-xr-x 1 root root 292728 2010-03-30 08:07 dbus-daemon -rwxr-xr-x 1 root root 5524 2010-03-30 08:07 dbus-uuidgen -rwxr-xr-x 1 root root 54996 2010-03-04 19:29 dd -rwxr-xr-x 1 root root 67316 2010-03-04 19:29 df -rwxr-xr-x 1 root root 104528 2010-03-04 19:29 dir -rwxr-xr-x 1 root root 5524 2010-03-22 10:51 dmesg -rwxr-xr-x 1 root root 13824 2010-03-10 11:12 dnsdomainname root@ubuntu:~/resource/shell-study/0506-2013#
最后提一下逻辑判断方法
-a
逻辑与
exp1 -a exp2 如果表达式exp1和exp2都为真的话, 那么结果为真.
-o
逻辑或
exp1 -o exp2 如果表达式exp1和exp2中至少有一个为真的话, 那么结果为真.
这与Bash中的比较操作符&&和||非常相像, 但是这个两个操作符是用在双中括号结构中的.
比如用在【【】】中 [[ condition1 && condition2 ]]
-o和-a操作符一般都是和test命令或者是单中括号结构一起使用的, if [ "$exp1" -a "$exp2" ]
先到这里了,O(∩_∩)O~
我的专栏地址:http://blog.csdn.net/column/details/shell-daily-study.html
待续。。。。。
相关文章推荐
- perl文件测试操作符
- 字符串测试/文件测试/整数比较/逻辑操作符
- Linux Shell Bash 文件测试操作符
- shell 常用文件、字符串、二元整数测试操作符-持续更新中
- 高级Bash脚本编程指南(29):文件与归档命令(二)
- perl 文件测试操作符汇总
- 高级Bash脚本编程指南(6):条件测试结构
- Perl – 文件测试操作符
- 高级Bash脚本编程指南(17):测试和分支(case与select结构)
- 高级Bash脚本编程指南(28):文件与归档命令(一)
- 不要忽略文件测试操作符
- ABS之条件测试文件测试操作符
- 高级Bash脚本编程指南(8):操作符
- 《高级Bash脚本编程指南》学习笔记(9)——基础:文件测试操作符
- 26_Shell语言――――if条件判断之文件测试、短路操作符
- 高级文件编程——标准文件操作的函数(转)
- redis 由浅入深之 高级(数据备份与恢复、安全、性能测试和客户端连接)
- 编写测试驱动环境文件出现LNK2019错误
- 对三种编码文件的测试
- linux高级文件系统管理概述:处理交换分区、设置文件系统配额、配置raid和逻辑卷