7.2 文件测试操作
下列每一个test选项在满足条件时,返回0(真)。
-e
检测文件是否存在
-a
检测文件是否存在
等价于 -e。不推荐使用,已被弃用^1。
-f
文件是常规文件(regular file),而非目录或 设备文件
-s
文件大小不为0
-d
文件是一个目录
-b
文件是一个 块设备
-c
文件是一个 字符设备
1. device0="/dev/sda2" # / (根目录)
2. if [ -b "$device0" ]
3. then
4. echo "$device0 is a block device."
5. fi
7. # /dev/sda2 是一个块设备。
11. device1="/dev/ttyS1" # PCMCIA 调制解调卡
12. if [ -c "$device1" ]
13. then
14. echo "$device1 is a character device."
15. fi
17. # /dev/ttyS1 是一个字符设备。
-p
文件是一个 管道设备
1. function show_input_type()
2. {
3. [ -p /dev/fd/0 ] && echo PIPE || echo STDIN
4. }
6. show_input_type "Input" # STDIN
7. echo "Input" | show_input_type # PIPE
9. # 这个例子由 Carl Anderson 提供。
-h
文件是一个 符号链接
-L
文件是一个符号链接
-S
文件是一个 套接字
-t
文件(文件描述符)与终端设备关联
该选项通常被用于 测试 脚本中的 stdin [ -t 0 ] 或 stdout [ -t 1 ] 是否为终端设备。
-r
该文件对执行测试的用户可读
-w
该文件对执行测试的用户可写
-x
该文件可被执行测试的用户所执行
-g
文件或目录设置了 set-group-id sgid 标志
如果一个目录设置了 sgid 标志,那么在该目录中所有的新建文件的权限组都归属于该目录的权限组,而非文件创建者的权限组。该标志对共享文件夹很有用。
-u
文件设置了 set-user-id suid 标志。
一个属于 root 的可执行文件设置了 suid 标志后,即使是一个普通用户执行也拥有 root 权限[^2]。对需要访问硬件设备的可执行文件(例如 pppd 和 cdrecord)很有用。如果没有 suid 标志,这些可执行文件就不能被非 root 用户所调用了。
1. -rwsr-xr-t 1 root 178236 Oct 2 2000 /usr/sbin/pppd
设置了 suid 标志后,在权限中会显示 s。
-k
设置了粘滞位(sticky bit)。
标志粘滞位是一种特殊的文件权限。如果文件设置了粘滞位,那么该文件将会被存储在高速缓存中以便快速访问[^3]。如果目录设置了该标记,那么它将会对目录的写权限进行限制,目录中只有文件的拥有者可以修改或删除文件。设置标记后你可以在权限中看到 t。
1. drwxrwxrwt 7 root 1024 May 19 21:26 tmp/
如果一个用户不是设置了粘滞位目录的拥有者,但对该目录有写权限,那么他仅仅可以删除目录中他所拥有的文件。这可以防止用户不经意间删除或修改其他人的文件,例如 /tmp 文件夹。(当然目录的所有者可以删除或修改该目录下的所有文件)
-O
执行用户是文件的拥有者
-G
文件的组与执行用户的组相同
-N
文件在在上次访问后被修改过了
f1 -nt f2
文件 f1 比文件 f2 新
f1 -ot f2
文件 f1 比文件 f2 旧
f1 -ef f2
文件 f1 和文件 f2 硬链接到同一个文件
!
取反——对测试结果取反(如果条件缺失则返回真)。
样例 7-4. 检测链接是否损坏
1. #!/bin/bash
2. # broken-link.sh
3. # Lee bigelow <ligelowbee@yahoo.com> 编写。
4. # ABS Guide 经许可可以使用。
6. # 该脚本用来发现输出损坏的链接。输出的结果是被引用的,
7. #+ 所以可以直接导到 xargs 中进行处理 :)
8. # 例如:sh broken-link.sh /somedir /someotherdir|xargs rm
9. #
10. # 更加优雅的方式:
11. #
12. # find "somedir" -type 1 -print0|\
13. # xargs -r0 file|\
14. # grep "broken symbolic"|
15. # sed -e 's/^\|: *broken symbolic.*$/"/g'
16. #
17. # 但是这种方法不是纯 Bash 写法。
18. # 警告:小心 /proc 文件下的文件和任意循环链接!
19. ############################################
22. # 如果不给脚本传任何参数,那么 directories-to-search 设置为当前目录
23. #+ 否则设置为传进的参数
24. #####################
26. [ $# -eq 0 ] && directory=`pwd` || directory=$@
29. # 函数 linkchk 是用来检测传入的文件夹中是否包含损坏的链接文件,
30. #+ 并引用输出他们。
31. # 如果文件夹中包含子文件夹,那么将子文件夹继续传给 linkchk 函数进行检测。
32. #################
34. linkchk () {
35. for element in $1/*; do
36. [ -h "$element" -a ! -e "$element" ] && echo \"$element\"
37. [ -d "$element" ] && linkchk $element
38. # -h 用来检测是否是链接,-d 用来检测是否是文件夹。
39. done
40. }
42. # 检测传递给 linkchk() 函数的参数是否是一个存在的文件夹,
43. #+ 如果不是则报错。
44. ################
45. for directory in $direcotrys; do
46. if [ -d $directory ]
47. then linkchk $directory
48. else
49. echo "$directory is not a directory"
50. echo "Usage $0 dir1 dir2 ..."
51. fi
52. done
54. exit $?
样例 31-1,样例 11-8,样例 11-3,样例 31-3和样例 A-1 也包含了文件测试操作符的使用。
1. Deprecate
…
To pray against, as an evil;
to seek to avert by prayer;
to desire the removal of;
to seek deliverance from;
to express deep regret for;
to disapprove of strongly.
[^2]: 注意使用 suid 的可执行文件可能会带来安全问题。suid 标记对 shell 脚本没有影响。 [^3]: 在 Linux 系统中,文件已经不使用粘滞位了, 粘滞位只作用于目录。
