美文网首页
Shell基础脚本-文件测试操作

Shell基础脚本-文件测试操作

作者: Chris0Yang | 来源:发表于2021-11-18 21:37 被阅读0次

下列每一个运算符在满足其下条件时,返回的结果为真

( -e )

检测文件是否存在

( -a )

检测文件是否存在
等价于 -e。不推荐使用,已被弃用。

( -f )

文件是常规文件(regular file),而非目录或 设备文件

( -s )

文件大小不为0

( -d )

文件是一个目录

( -b )

文件是一个 块设备

( -c )

文件是一个 字符设备

device0="/dev/sda2"    # /   (根目录)
if [ -b "$device0" ]
then
  echo "$device0 is a block device."
fi

# /dev/sda2 是一个块设备。



device1="/dev/ttyS1"   # PCMCIA 调制解调卡
if [ -c "$device1" ]
then
  echo "$device1 is a character device."
fi

# /dev/ttyS1 是一个字符设备。

( -p )

文件是一个 管道设备

function show_input_type()
{
   [ -p /dev/fd/0 ] && echo PIPE || echo STDIN
}

show_input_type "Input"                           # STDIN
echo "Input" | show_input_type                    # PIPE

( -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 权限。
对需要访问硬件设备的可执行文件(例如 pppd 和 cdrecord)很有用。
如果没有 suid 标志,这些可执行文件就不能被非 root 用户所调用了

-rwsr-xr-t    1 root       178236 Oct  2  2000 /usr/sbin/pppd

设置了 suid 标志后,在权限中会显示 s

( -k )

设置了粘滞位(sticky bit)
标志粘滞位是一种特殊的文件权限。如果文件设置了粘滞位,那么该文件将会被存储在高速缓存中以便快速访问。如果目录设置了该标记,那么它将会对目录的写权限进行限制,目录中只有文件的拥有者可以修改或删除文件。设置标记后你可以在权限中看到 t

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 硬链接到同一个文件

( ! )

取反——对测试结果取反(如果条件缺失则返回真)

样例-1. 检测链接是否损坏

#!/bin/bash
# broken-link.sh
# Lee bigelow <ligelowbee@yahoo.com> 编写。
# ABS Guide 经许可可以使用。

#  该脚本用来发现输出损坏的链接。输出的结果是被引用的,
#+ 所以可以直接导到 xargs 中进行处理 :)
#  例如:sh broken-link.sh /somedir /someotherdir|xargs rm
#
#  更加优雅的方式:
#
#  find "somedir" -type 1 -print0|\
#  xargs -r0 file|\
#  grep "broken symbolic"|
#  sed -e 's/^\|: *broken symbolic.*$/"/g'
#
#  但是这种方法不是纯 Bash 写法。
#  警告:小心 /proc 文件下的文件和任意循环链接!
############################################


#  如果不给脚本传任何参数,那么 directories-to-search 设置为当前目录
#+ 否则设置为传进的参数
#####################

[ $# -eq 0 ] && directory=`pwd` || directory=$@


#  函数 linkchk 是用来检测传入的文件夹中是否包含损坏的链接文件,
#+ 并引用输出他们。
#  如果文件夹中包含子文件夹,那么将子文件夹继续传给 linkchk 函数进行检测。
#################

linkchk () {
    for element in $1/*; do
      [ -h "$element" -a ! -e "$element" ] && echo \"$element\"
      [ -d "$element" ] && linkchk $element
    # -h 用来检测是否是链接,-d 用来检测是否是文件夹。
    done
}

#  检测传递给 linkchk() 函数的参数是否是一个存在的文件夹,
#+ 如果不是则报错。
################
for directory in $direcotrys; do
    if [ -d $directory ]
        then linkchk $directory
        else
            echo "$directory is not a directory"
            echo "Usage $0 dir1 dir2 ..."
    fi
done

exit $?

其他比较操作

二元比较操作比较变量或者数量。注意整数和字符串比较使用的是两套运算符

整数比较

( -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" ] 和上面不等价

( == )

等于

if [ "$a" == "$b" ]

= 同义 == 运算符在 双方括号和单方括号里表现不同

[[ $a == z* ]]   # $a 以 "z" 开头时为真(模式匹配)
[[ $a == "z*" ]] # $a 等于 z* 时为真(字符匹配)

[ $a == z* ]     # 发生文件匹配和字符分割。
[ "$a" == "z*" ] # $a 等于 z* 时为真(字符匹配)

( != )

不等于

if [ "$a" != "$b" ]

[[ ... ]] 结构中会进行模式匹配。

( < )

小于,按照 ASCII码排序

if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]

注意在 [] 结构里 < 需要被 转义

( > )

大于,按照 ASCII 码排序

if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]

注意在 [] 结构里 > 需要被转义

( -z )

字符串为空,即字符串长度为0

String=''   # 长度为0的字符串变量。

if [ -z "$String" ]
then
  echo "\$String is null."
else
  echo "\$String is NOT null."
fi     # $String is null.

( -n )

字符串非空(null)
使用 -n 时字符串必须是在括号中且被引用的
使用 ! -z 判断未引用的字符串或者直接判断 通常可行,但是非常危险
判断字符串时一定要引用
样例-2. 算术比较和字符串比较

#!/bin/bash

a=4
b=5

# 这里的 "a" 和 "b" 可以是整数也可以是字符串。
# 因为 Bash 的变量是弱类型的,因此字符串和整数比较有很多相同之处。

# 在 Bash 中可以用处理整数的方式来处理全是数字的字符串。
# 但是谨慎使用。

echo

if [ "$a" -ne "$b" ]
then
  echo "$a is not equal to $b"
  echo "(arithmetic comparison)"
fi

echo

if [ "$a" != "$b" ]
then
  echo "$a is not equal to $b."
  echo "(string comparison)"
  #     "4"  != "5"
  # ASCII 52 != ASCIII 53
fi

# 在这个例子里 "-ne" 和 "!=" 都可以。

echo

exit 0

样例-3. 测试字符串是否为空(null)

#!/bin/bash
# str-test.sh: 测试是否为空字符串或是未引用的字符串。

# 使用 if [ ... ] 结构

# 如果字符串未被初始化,则其值是未定义的。
# 这种状态就是空 "null"(并不是 0)。

if [ -n $string1 ]    # 并未声明或是初始化 string1。
then
  echo "String \"string1\" is not null."
else
  echo "String \"string1\" is null."
fi
# 尽管没有初始化 string1,但是结果显示其非空。

echo

# 再试一次。

if [ -n "$string1" ]   # 这次引用了 $string1。
then
  echo "String \"string1\" is not null."
else
  echo "String \"string1\" is null."
fi                    # 在测试括号内引用字符串得到了正确的结果。

echo

if [ $string1 ]       # 这次只有一个 $string1。
then
  echo "String \"string1\" is not null."
else
  echo "String \"string1\" is null."
fi                    # 结果正确。
# 独立的 [ ... ] 测试运算符可以用来检测字符串是否为空。
# 但是最好将字符串进行引用(if [ "$string1" ])。
#
# Stephane Chazelas 指出:
#    if [ $string1 ]    只有一个参数 "]"
#    if [ "$string1" ]  则有两个参数,空的 "$string1" 和 "]"


echo


string1=initialized

if [ $string1 ]       # $string1 这次仍然没有被引用。
then
  echo "String \"string1\" is not null."
else
  echo "String \"string1\" is null."
fi                    # 这次的结果仍然是正确的。
# 最好将字符串引用("$string1")


string1="a = b"

if [ $string1 ]       # $string1 这次仍然没有被引用。
then
  echo "String \"string1\" is not null."
else
  echo "String \"string1\" is null."
fi                    # 这次没有引用就错了。

exit 0   

样例-4. zmore

#!/bin/bash
# zmore

# 使用筛选器 'more' 查看 gzipped 文件。

E_NOARGS=85
E_NOTFOUND=86
E_NOTGZIP=87

if [ $# -eq 0 ] # 作用和 if [ -z "$1" ] 相同。
# $1 可以为空: zmore "" arg2 arg3
then
  echo "Usage: `basename $0` filename" >&2
  # 将错误信息通过标准错误 stderr 进行输出。
  exit $E_NOARGS
  # 脚本的退出状态为 85.
fi

filename=$1

if [ ! -f "$filename" ]   # 引用字符串以防字符串中带有空格。
then
  echo "File $filename not found!" >&2   # 通过标准错误 stderr 进行输出。
  exit $E_NOTFOUND
fi

if [ ${filename##*.} != "gz" ]
# 在括号内使用变量代换。
then
  echo "File $1 is not a gzipped file!"
  exit $E_NOTGZIP
fi

zcat $1 | more

# 使用筛选器 'more'
# 也可以用 'less' 替代

exit $?   # 脚本的退出状态由管道 pipe 的退出状态决定。
#  实际上 "exit $?" 不一定要写出来,
#+ 因为无论如何脚本都会返回最后执行命令的退出状态。

复合比较

( -a )

逻辑与
exp1 -a exp2 返回真当且仅当 exp1 和 exp2 均为真

( -o )

逻辑或
如果 exp1exp2 为真,则 exp1 -o exp2 返回真。
以上两个操作和 双方括号结构中的 Bash 比较运算符号 &&|| 类似

[[ condition1 && condition2 ]]

测试操作 -o-a 可以在 test 命令或在测试括号中进行

if [ "$expr1" -a "$expr2" ]
then
  echo "Both expr1 and expr2 are true."
else
  echo "Either expr1 or expr2 is false."
fi

rihad 指出:

[ 1 -eq 1 ] && [ -n "`echo true 1>&2`" ]   # 真
[ 1 -eq 2 ] && [ -n "`echo true 1>&2`" ]   # 没有输出
# ^^^^^^^ 条件为假。到这里为止,一切都按预期执行。

# 但是
[ 1 -eq 2 -a -n "`echo true 1>&2`" ]       # 真
# ^^^^^^^ 条件为假。但是为什么结果为真?

# 是因为括号内的两个条件子句都执行了么?
[[ 1 -eq 2 && -n "`echo true 1>&2`" ]]     # 没有输出
# 并不是。

#  所以显然 && 和 || 具备“短路”机制,
#+ 例如对于 &&,若第一个表达式为假,则不执行第二个表达式直接返回假,
#+ 而 -a 和 -o 则不是。

相关文章

  • Shell基础脚本-文件测试操作

    下列每一个运算符在满足其下条件时,返回的结果为真 ( -e ) 检测文件是否存在 ( -a ) 检测文件是否存在等...

  • shell脚本基础

    编写脚本 编程基础 shell脚本 创建shell脚本 变量 运算 测试 配置用户的环境

  • “Linux命令行与shell脚本编程”-构建基本脚本

    shell脚本基础 在创建shell脚本文件时,必须在文件的第一行指定是使用的shell。#!/bin/bash。...

  • 005.shell基础

    shell脚本基础 shell脚本可以输入多个命令并处理每个命令的结果。 创建shell脚本时,需要在文件的第一行...

  • shell

    shell脚本在linux中应用广泛,之前一直选用python写脚本来进行一些文件操作,但是最后发现shell脚本...

  • 第6次课-Shell脚本语言-第6讲

    内容一:Shell脚本->数据库SQL语句->基础(回顾) 内容二:Shell脚本语言->数据库操作->在Shel...

  • shell-14 shell对文件的操作 sed

    shell对文件的操作 一、简介 在shell脚本编写中,时常会用到对文件的相关操作,比如增加内容,修改内容,删除...

  • Shell语言学习(四)

    内容一:Shell脚本语言-管道 内容二:Shell脚本语言-重定向 重定向目的:就是操作文件输入和输出1、学习-...

  • shell面试题

    脚本传参[http://it.agr-api.com/shell/param_deliver.html]文件操作[...

  • shell对文件的操作

    shell对文件的操作 简介 sed命令 sed小技巧 一、简介 在shell脚本编写中,时常会用到对文件的相关操...

网友评论

      本文标题:Shell基础脚本-文件测试操作

      本文链接:https://www.haomeiwen.com/subject/clqctrtx.html