如何正确检查Bash或者Shell中是否存在文件(带有示例)

时间:2020-01-09 10:37:19  来源:igfitidea点击:

在本教程中,我将介绍我们可以在bash或者shell脚本中使用的不同属性,以检查文件和目录。
我们可以将bash条件表达式与[[]]一起使用,或者将test与[]一起使用以检查文件是否存在。

1. Bash/Shell:检查文件是否存在并且是常规文件

本节显示检查bash中是否存在常规文件的示例。

1.1:方法1:使用单括号或者双括号

使用双括号[[..]]

#!/bin/bash
FILE="/etc/passwd"
if [[ -f $FILE ]];then
    echo "$FILE exists"
else
    echo "$FILE doesn't exist"
fi

使用单括号" [..]"

#!/bin/bash
FILE="/etc/passwd"
if [ -f $FILE ];then
    echo "$FILE exists"
else
    echo "$FILE doesn't exist"
fi

1.2:方法2:使用测试命令

" test"命令用于检查文件类型并比较值。

#!/bin/bash
FILE="/etc/passwd"
if test -f $FILE; then
    echo "$FILE exists"
else
    echo "$FILE missing"
fi

1.3:方法3:单行

在此示例中,我们可以在此处使用单括号或者双括号。
我建议在shell中编写一个线性代码时始终使用双括号,因为这样可以最大程度地减少发生单词拆分时在控制台上收到警告的风险。

#!/bin/bash
FILE="/etc/passwd"
[[ -f $FILE ]] && echo "$FILE exists" || echo "$FILE missing"

如果成功,&&之后的语句将被执行。
如果第一个条件返回FALSE,则将执行带有||的语句。

类似地,使用test命令检查bash或者shell脚本中的常规文件是否单行存在。

#!/bin/bash
FILE="/etc/passwd"
test -f $FILE && echo "$FILE exists" || echo "$FILE missing"

2. Bash/Shell:检查文件是否存在(为空或者不为空)

要检查文件是否存在,是否为空或者是否包含某些内容,请使用-s属性

2.1:方法1:使用单括号或者双括号

使用双括号" .."检查文件是否存在以及是否为空

#!/bin/bash
FILE="/etc/passwd"
if [[ -s $FILE ]]; then
   echo "$FILE exists and not empty"
else
   echo "$FILE doesn't exist or is empty"
fi

使用双括号" [..]"检查文件是否存在以及是否为空

if [ -s $FILE ]; then
   echo "$FILE exists and not empty"
else
   echo "$FILE doesn't exist or is empty"
fi

2.2:方法2:使用测试命令

使用测试命令,我们结合使用-s属性来检查文件是否存在,是否为空或者是否包含某些内容:

#!/bin/bash
FILE="/etc/passwd"
if test -s $FILE; then
    echo "$FILE exists and not empty"
else
    echo "$FILE doesn't exist or is empty"
fi

2.3:方法3:单行

对于这样的一个衬里,我们可以使用双括号或者单括号,但正如我之前所说,我建议使用双括号。

#!/bin/bash
FILE="/etc/passwd"
test -s $FILE && echo "$FILE exists and not empty" || echo "$FILE doesn't exist or is empty"

与测试命令类似,我们可以使用&&||运算符在shell脚本中的单行命令中检查文件。

#!/bin/bash
FILE="/etc/passwd"
[[ -s $FILE ]] && echo "$FILE exists and not empty" || echo "$FILE doesn't exist or is empty"

3. Bash/Shell:检查目录是否存在

我希望我们知道在Linux中所有内容都是文件。
因此,以这种方式,目录也被视为文件。
我们可以使用-d属性来检查shell编程中是否存在目录。

3.1:方法1:使用双括号或者单括号

我们可以在单..或者双括号..中使用-d属性来检查目录是否存在。

#!/bin/bash
DIR="/var/log"
if [[ -d $DIR ]]; then
   echo "$DIR exists"
else
   echo "$DIR doesn't exist"
fi

同样,在此示例中,我们使用单括号来检查目录是否已在Shell脚本中预设。

#!/bin/bash
DIR="/var/log"
if [ -d $DIR ]; then
   echo "$DIR exists"
else
   echo "$DIR doesn't exist"
fi

3.2:方法2:使用测试命令

在此示例中,我们将使用test命令在执行某些任务之前确保目录是否存在。

#!/bin/bash
DIR="/var/log"
if test -d $DIR; then
    echo "$DIR exists"
else
    echo "$DIR doesn't exist"
fi

3.3:方法3:单行

在此示例中,我们将使用单行形式的单括号和双括号来检查目录。
如果第一个条件为TRUE,则执行" &&"运算符后的语句;如果为FALSE,则将执行" |||"条件的语句。

#!/bin/bash
DIR="/var/log"
[[ -d $DIR ]] && echo "$DIR exists" || echo "$DIR doesn't exist"

我建议在shell程序编程中使用这样的一个单行代码,而不是使用..而不是[..]。

&&||类似,我们可以使用test命令检查目录是否存在

#!/bin/bash
DIR="/var/log"
test -d $DIR && echo "$DIR exists" || echo "$DIR doesn't exist"

4. Bash/Shell:检查目录是否存在(空或者不为空)

正如我在本教程的所有其他示例和方案中所使用的那样,没有shell属性。
但是我们确实有一些技巧可以用来检查目录是否为空或者非空。

4.1:方法1:列出目录内容并验证

在此示例中,我们将列出目录的内容,抑制输出,然后根据退出代码检查目录是否为空或者包含某些内容

#!/bin/bash
DIR="/tmp"
if ls -1qA $DIR | grep -q . ; then
    echo "$DIR is not -empty"
else
    echo "$DIR is empty"
fi

我们还可以通过设置NOT()条件来扭转这种情况。
因此,它看起来像:

#!/bin/bash
DIR="/tmp"
if ! ls -1qA $DIR | grep -q . ; then
    echo "$DIR is empty"
else
    echo "$DIR is not-empty"
fi

在两个示例脚本中,输出将相同。

4.2:方法2:使用find命令

我们可以使用find命令,然后取消输出以检查目标目录是否包含某些内容。

#!/bin/bash
DIR="/tmp"
if find -- "$DIR" -prune -type d -empty | grep -q . ; then
    echo "$DIR is empty"
else
    echo "$DIR is not-empty"
fi

4.3:方法3:列出内容

再次如我所说,由于没有简便的方法可以检查目录是否为空或者不使用某些属性,因此我们将列出目录的内容。
如果没有输出,则目录为空或者不为空

#!/bin/bash
DIR="/tmp"
if [[ -z "$(ls -A -- "$DIR")" ]] ; then
    echo "$DIR is empty"
else
    echo "$DIR is not-empty"
fi

5. Bash/Shell:测试文件的属性列表

同样,我们可以将更多其他属性与Shell脚本一起使用以检查不同的文件类型,例如符号链接,文件权限等。

属性作用
-a FILE如果文件 FILE存在 ,则为True
-b FILE如果文件 FILE存在 且为块特殊文件,则为True
-c FILE如果文件 FILE存在 且是字符特殊文件,则为True
-d FILE如果文件 FILE存在 且为目录,则为True
-e FILE如果文件 FILE存在 ,则为True
-f FILE如果文件 FILE存在 且是常规文件,则为True
-g FILE如果文件 FILE存在 设置了其设置的组id位,则为True
-h FILE如果文件 FILE存在 且为符号链接,则为True
-k FILE如果文件 FILE存在 并且设置了“粘性”位,则为True
-p FILE如果文件 FILE存在 且为命名管道(FIFO),则为True
-r FILE如果文件 FILE存在 且可读,则为True
-s FILE如果文件 FILE存在 且大小大于零,则为True
-u FILE如果文件 FILE存在 设置了其设置的用户id位,则为True
-w FILE如果文件 FILE存在 且可写入,则为True
-x FILE如果文件 FILE存在 且可执行,则为True
-G FILE如果文件 FILE存在 由有效组id所拥有,则为True
-L FILE如果文件 FILE存在 且为符号链接,则为True
-N FILE如果文件 FILE存在 自上次读取以来已修改,则为True
-o FILE如果文件 FILE存在 由有效用户id拥有,则为True
-S FILE如果文件 FILE存在 为套接字,则为True
FILE1 -ef FILE2如果'FILE1'和'FILE2'引用相同的设备和inode编号,则为True
FILE1 -nt FILE2如果'FILE1'比'FIL21'新(根据修改日期),或者'FILE1'存在,FILE2不存在,则为True
FILE1 -ot FILE2如果'FILE1'比'FIL21'旧(根据修改日期),或者'FILE2'存在,FILE1不存在,则为True