最近和shell脚本打交道比较多,虽然很多内容之前或多或少都有所接触,但时间一久了难免有些忘记的,所以,在此记录一下做个学习/备份,同时感谢别人的热心分享/整理:
文件状态测试
-b filename | 当filename 存在并且是块文件时返回真(返回0) |
-c filename | 当filename 存在并且是字符文件时返回真 |
-d pathname | 当pathname 存在并且是一个目录时返回真 |
-e pathname | 当由pathname 指定的文件或目录存在时返回真 |
-f filename | 当filename 存在并且是正规文件时返回真 |
-g pathname | 当由pathname 指定的文件或目录存在并且设置了SGID 位时返回真 |
-h filename | 当filename 存在并且是符号链接文件时返回真 (或 -L filename) |
-k pathname | 当由pathname 指定的文件或目录存在并且设置了”粘滞”位时返回真 |
-p filename | 当filename 存在并且是命名管道时返回真 |
-r pathname | 当由pathname 指定的文件或目录存在并且可读时返回真 |
-s filename | 当filename 存在并且文件大小大于0 时返回真 |
-S filename | 当filename 存在并且是socket 时返回真 |
-t fd | 当fd 是与终端设备相关联的文件描述符时返回真 |
-u pathname | 当由pathname 指定的文件或目录存在并且设置了SUID 位时返回真 |
-w pathname | 当由pathname 指定的文件或目录存在并且可写时返回真 |
-x pathname | 当由pathname 指定的文件或目录存在并且可执行时返回真 |
-O pathname | 当由pathname 存在并且被当前进程的有效用户id 的用户拥有时返回真(字母O 大写) |
-G pathname | 当由pathname 存在并且属于当前进程的有效用户id 的用户的用户组时返回真 |
file1 -nt file2 | file1 比file2 新时返回真 |
file1 -ot file2 | file1 比file2 旧时返回真 |
f1 -ef f2 | files f1 and f2 are hard links to the same file |
if [ -b /dev/hda ] ;then echo "yes" ;else echo "no";fi // 将打印 yes test -c /dev/hda ; echo $? // 将打印 1 表示test 命令的返回值为1,/dev/hda 不是字符设备 [ -w /etc/passwd ]; echo $? // 查看对当前用户而言,passwd 文件是否可写
测试时逻辑操作符
-a | 逻辑与,操作符两边均为真,结果为真,否则为假。 |
-o | 逻辑或,操作符两边一边为真,结果为真,否则为假。 |
! | 逻辑否,条件为假,结果为真。 |
[ -w result.txt -a -w score.txt ] ;echo $? // 测试两个文件是否均可写
常见字符串测试
-z string | 字符串string 为空串(长度为0)时返回真 |
-n string | 字符串string 为非空串时返回真 |
str1 = str2 | 字符串str1 和字符串str2 相等时返回真 |
str1 == str2 | 同 = |
str1 != str2 | 字符串str1 和字符串str2 不相等时返回真 |
str1 < str2 | 按字典顺序排序,字符串str1 在字符串str2 之前 |
str1 > str2 | 按字典顺序排序,字符串str1 在字符串str2 之后 |
name="zqf"; [ $name = "zqf" ];echo $? // 打印 0 表示变量name 的值和字符串"zqf"相等
常见数值测试
int1 -eq int2 | 如果int1 等于int2,则返回真 |
int1 -ne int2 | 如果int1 不等于int2,则返回真 |
int1 -lt int2 | 如果int1 小于int2,则返回真 |
int1 -le int2 | 如果int1 小于等于int2,则返回真 |
int1 -gt int2 | 如果int1 大于int2,则返回真 |
int1 -ge int2 | 如果int1 大于等于int2,则返回真 |
在 (()) 中的测试:
< | 小于(在双括号里使用) | ((“$a” < “$b”)) |
<= | 小于等于 (在双括号里使用) | ((“$a” <= “$b”)) |
> | 大于 (在双括号里使用) | ((“$a” > “$b”)) |
>= | 大于等于(在双括号里使用) | ((“$a” >= “$b”)) |
x=1 ; [ $x -eq 1 ] ; echo $? // 将打印 0 表示变量x 的值等于数字1 x=a ; [ $x -eq "1" ] // shell 打印错误信息 [: a: integer expression expected
test , [] , [[]]
因为 shell 和我们通常的编程语言不同,所以有些本属于程序语言本身的概念在 shell 中会难以理解。”基本功” 不好,就更容易 “犯困” 了。
以 bash 为例 (其他兼容 shell 差不多):
- test 和 [ 是 bash 的内部命令,GNU/linux 系统的 coreutils 软件包通 常也带 /usr/bin/test 和 /usr/bin/[ 命令。如果我们不用绝对路径指 明,通常我们用的都是 bash 自带的命令。
- [[ 是 bash 程序语言的关键字!
$ ls -l /usr/bin/[ /usr/bin/test -rwxr-xr-x 1 root root 37400 9月 18 15:25 /usr/bin/[ -rwxr-xr-x 1 root root 33920 9月 18 15:25 /usr/bin/test $ type [ [[ test [ is a shell builtin [[ is a shell keyword test is a shell builtin
绝大多数情况下,这个三个功能通用。但是命令和关键字总是有区别的。命令和 关键字的差别有多大呢?
如果是命令,它就和参数组合为一体被 shell 解释,那样比如 “>” “<” 就被 shell 解释为重定向符号了。关键字却不这样。
在 [[ 中使用 && 和 ||
[ 中使用 -a 和 -o 表示逻辑与和逻辑或。
[[ 中可以使用通配符
arch=i486 [[ $arch = i*86 ]] && echo "arch is x86!"
[[ 中匹配字符串或通配符,不需要引号
[[ $arch_com = i386 || $ARCH = i*86 ]] && cat >> $TFS_REPO <<EOF [tfs-i386] name=GTES11.3 prelim1 baseurl=${BASEURL}i386/ enabled=1 EOF
以上内容来自:Shell 条件测试
1. 关于某个文件名的『类型』侦测(存在与否),如 test -e filename
-e 该『文件名』是否存在?(常用)
-f 该『文件名』是否为文件(file)?(常用)
-d 该『文件名』是否为目录(directory)?(常用)
-b 该『文件名』是否为一个 block device 装置?
-c 该『文件名』是否为一个 character device 装置?
-S 该『文件名』是否为一个 Socket 文件?
-p 该『文件名』是否为一个 FIFO (pipe) 文件?
-L 该『文件名』是否为一个连结档?
2. 关于文件的权限侦测,如 test -r filename
-r 侦测该文件名是否具有『可读』的属性?
-w 侦测该文件名是否具有『可写』的属性?
-x 侦测该文件名是否具有『可执行』的属性?
-u 侦测该文件名是否具有『SUID』的属性?
-g 侦测该文件名是否具有『SGID』的属性?
-k 侦测该文件名是否具有『Sticky bit』的属性?
-s 侦测该文件名是否为『非空白文件』?
3. 两个文件之间的比较,如: test file1 -nt file2
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
-ef 判断 file2 与 file2 是否为同一文件,可用在判断 hard link 的判定上。 主要意义在判定,两个文件是否均指向同一个 inode 哩!
4. 关于两个整数之间的判定,例如 test n1 -eq n2
-eq 两数值相等 (equal)
-ne 两数值不等 (not equal)
-gt n1 大于 n2 (greater than)
-lt n1 小于 n2 (less than)
-ge n1 大于等于 n2 (greater than or equal)
-le n1 小于等于 n2 (less than or equal)
5. 判定字符串的数据
test -z string 判定字符串是否为 0 ?若 string 为空字符串,则为 true
test -n string 判定字符串是否非为 0 ?若 string 为空字符串,则为 false。
注: -n 亦可省略
test str1 = str2 判定 str1 是否等于 str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false
6. 多重条件判定,例如: test -r filename -a -x filename
-a (and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传 true。
-o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。
! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true
总结下来:
条件测试/test命令测试的表达式类型可分为四类:
- 表达式判断
- 字符串比较
- 数字比较
- 文件比较
《 “Shell条件测试” 》 有 3 条评论
设置脚本仅运行一次,且只在凌晨5点左右运行:
`
local ffmpeg_checked=”${SCRIPT_SELF_PATH}/${SCRIPT_NAME}.ffmpeg” #在当前目录下以当前脚本名创建一个后缀为ffmpeg的文件,用于判断脚本/函数之前是否已运行过
test -f “$ffmpeg_checked” && return 1 #已运行过,则立即退出
touch “$ffmpeg_checked” #第一次运行,则会创建该文件
local hour=$(date +%H) #(00..23)
test “05” = $hour || return 2 #仅当当前小时数为05时才运行,防止在业务高峰期运行造成故障
`
suid, sgid, sticky简介
http://www.178linux.com/82849
http://www.linuxnix.com/suid-set-suid-linuxunix/
https://tecadmin.net/understanding-sticky-bit-suid-and-sgid-in-linux/
https://en.wikipedia.org/wiki/Setuid
[…] SHELL条件测试 […]