学习Bash文件测试运算符,附例

Bash非常灵活,并提供了各种测试文件的选项。如果您想要测试文件的方法,Bash文件测试操作符将带您进入。

在本教程中,您将学习不同的文件测试操作符以及如何使用它们来测试文件是否存在、是否可读、是否为空等。

继续阅读并与Bash文件测试操作符交友!

先决条件

本教程将进行实践演示。如果您想跟着做,请确保您具有以下内容:

  • A Linux system with Bash installed – This tutorial uses Ubuntu 20.04.

大多数Linux发行版默认安装了Bash。但是,如果您使用Windows,您可以安装Windows子系统以获取Bash shell。

  • A user account with sudo privileges to run commands as root – This tutorial uses a root account for simplicity. But using a non-root user with sudo access is always recommended.
  • 本教程假设您可以访问Linux系统的SSH。

什么是 Bash 文件测试操作符?

在您开始使用测试操作符之前,先了解它们的工作原理。文件测试操作符可以让您测试文件的各个方面,比如文件是否存在、可读/可写等。

使用文件测试操作符可以帮助您避免在 Bash 脚本中出现错误。下面的代码是 if 语句的模板。if-else 语句是您经常在 Bash 脚本中看到的强大工具。

请记住,代码块的 then 和 else 部分是可选的。您可以在不使用它们的情况下使用 if 语句。

# 代表您要测试的文件。
# 将 file_name 替换为要测试的目标文件的名称。
FILE="file_name"
# 运算符 - 要使用的文件测试操作符。
if [ Operator $FILE ]

then
 # 如果运算符返回 true 要执行的任务。
 do something

else
 # 如果运算符返回 false 要执行的任务。
 do something

fi

检查文件是否存在

你已经见识过测试运算符的工作原理,但这还不足以更好地理解它们的使用要点。所以,我们从一个基本示例开始,比如检查文件是否存在。

在现实世界中,你可能希望在创建配置文件之前检查其是否存在。你不想浪费时间从头开始构建一个配置文件,只是为了发现相同的文件已经存在了。

要检查文件是否已经存在:

1. 打开你的终端,并运行下面的touch命令来创建一个新的 test.txt 文件。这个命令不会提供输出,但你将在下一步中验证文件是否存在。

touch test.txt

2. 接下来,运行以下ls命令来列出你的工作目录中新创建的文件(test.txt)。

ls -al test.txt

下面的输出证实你已成功创建了test.txt文件。

现在你有了一个测试文件,你可以按照以下步骤在Bash脚本中使用样板代码块来检查文件是否存在。

Listing the newly-created file

3. 运行下面的命令来创建(touch)并打开一个新的shell脚本文件(if_file_exists.sh),在你喜欢的文本编辑器(nano)中。

touch if_file_exists.sh && nano if_file_exists.sh

4. 现在,将下面的代码填入你的新文件if_file_exists.sh 中,保存文件并关闭编辑器。

  • 运行一个if-else语句来测试指定文件是否存在。
  • 如果操作符返回true,则会收到文件存在的消息。
  • 如果操作符返回true,则会收到文件不存在的消息。但是这次,文件会自动创建,采用你在FILE变量中定义的名称。

文件顶部的#!/bin/bash行被称为shebang。shebang告诉你的系统要使用哪个解释器来运行脚本,在这种情况下是Bash。如果不包括shebang,你的系统将使用默认解释器,这可能不是Bash。缺少shebang可能导致脚本执行失败。

#!/bin/bash
# FILE - 保存要测试的文件的值的变量。
# 通过更改$FILE变量的值,可以重用相同的代码块来测试不同的文件。
  # 通过更改$FILE变量的值,可以重用相同的代码块来测试不同的文件。
FILE="test.txt"

# -e操作符用于测试文件是否存在
if [ -e $FILE ]
then
  # 如果操作符返回true,则打印一条消息,表示文件存在。
  echo "$FILE exists"
else
  # 如果操作符返回true,则打印一条消息,表示文件不存在,
    # 然后使用在FILE变量中定义的名称创建文件。
  echo "$FILE does not exist, creating new file" && touch test.txt
fi

5. 运行以下命令以执行您的新脚本(if_file_exists.sh)

bash if_file_exists.sh

如果一切顺利,您将在终端中看到打印的test.txt存在消息,如下所示。

test.txt exists

6. 接下来,运行以下命令删除(rm -rf)测试文件(test.txt),并列出您的工作目录中的所有文件。

rm -rf test.txt
ls test.txt

下面,您可以验证test.txt不再列出。

Deleting the test file

7. 重新运行下面的命令以执行您的if_file_exists.sh脚本。

由于test.txt文件不再存在,当-e运算符返回false时,脚本将创建一个新的test.txt文件。

bash if_file_exists.sh
Rerun your if_file_exists.sh script

8. 最后,运行以下ls命令以列出您工作目录中的test.txt文件。

ls -al test.txt

下面的输出确认了您的脚本创建了一个新的test.txt文件。

Listing the new test.txt file

检查文件是否为普通文件还是特殊文件

在打开或处理文件之前,您可能希望首先检查该文件是否是普通文件还是特殊文件。为什么呢?特殊文件是存储在文件系统中的一种文件类型,因此请注意不要搞乱这些文件。

例如,当打开特殊文件时常见的错误是“没有这样的文件或目录”错误。当您尝试打开的文件不存在时,会出现此错误。但是当打开特殊文件而不是普通文件时,也可能会出现相同的错误。

在您的文本编辑器中打开一个新的special_file.sh文件,添加以下代码并保存更改。

以下代码与先前的代码类似。但是这段代码使用了-f运算符而不是-e运算符。

#!/bin/bash
# /dev/vmmon文件是一个特殊文件
  # 在Linux中用于与硬件设备通信。
FILE="/dev/vmmon"

# 检测文件 
if [ -f $FILE ]
then
  # 如果运算符返回true,则会显示一条消息
    # 表明该文件是一个常规文件。
  echo "$FILE is a regular file"

else
  # 如果运算符返回true,则会显示一条消息 
    # 表明该文件要么不存在要么是一个常规文件。
  echo "Either $FILE does not exist or is not a regular file"

fi

现在,运行下面的命令来执行你的special_file.sh脚本。

bash special_file.sh

由于/dev/vmmon中指定的文件在FILE变量中是一个特殊文件,你会收到下面的消息。

Checking if a file is a regular file

检查目录是否存在

到目前为止,你已经学会了如何检查文件是否存在。但是相同的方法是否适用于目录?是的,可以使用-d测试运算符。如果你计划根据目录是否存在来采取行动,这个运算符会很方便。

也许你想将一个目录中的所有文件复制到另一个目录中。如果目标目录不存在,你可以在复制文件之前创建它。

1. 运行以下ls命令来列出工作目录中的example-dir。

ls -la example-dir

由于该目录不存在,您将收到一个消息,显示找不到文件或目录。如果您不想因为目录不存在而中断流程,可以跳到下一步。

Listing the example-dir from the working directory

2. 接下来,在您的文本编辑器中打开一个名为if_dir_exists.sh的新文件,添加下面的代码并保存文件。以下代码测试指定目录是否存在,并根据-d运算符返回的值执行任务。

您可以通过使用否定运算符(!)来交换if和else语句的位置,从而实现相同的结果。在现实世界的情况下,!运算符可以帮助编写更清晰、更简洁的脚本。

#!/bin/bash
# 在dir变量中定义目录名称
dir=example_dir

# 测试目录(dir)是否存在
if [ ! -d $dir ]
then
  # 如果运算符返回true,则根据dir变量的值创建一个目录
  mkdir $dir
  # 将test.txt文件复制到新创建的目录中
  cp test.txt $dir
  # 打印上述任务的消息。
  echo "The directory has been created, and the test.txt file has been copied."
else
  # 如果运算符返回false,
    # 则echo命令会打印一条消息,指示目录已存在。
  echo "Directory $dir exists"
fi

3. 现在,运行以下命令来执行您的脚本(if_dir_exists.sh)

bash if_dir_exists.sh

你可以看到消息说目录已创建,并且test.txt文件已复制,因为example_dir 不存在。

Executing the if_dir_exists.sh to test if a directory exists

4. 最后,对example_dir 目录运行ls命令以确认目录存在并包含test.txt文件。

ls -la example_dir
Confirming the example_dir directory exists and contains the test.txt file

检查文件是否为空

你已经知道如何使用最常用的三个文件测试运算符(-e-f-d)来提升你的脚本技能。但还有其他运算符你可能会感兴趣。

通常,你会运行一个命令而不是突出显示一个文件的内容并将其复制到另一个文件。但是要稍等,因为你的目标文件可能不为空。

为什么不使用-s运算符来检查文件是否存在且不为空呢?该运算符在文件存在且大小大于零时返回true。

1. 在文本编辑器中打开一个名为empty_file.sh的新文件,添加以下代码,并保存文件。

以下代码测试指定文件是否为空,并根据-s运算符返回的值打印消息。

#!/bin/bash
# 定义目标文件的名称
FILE=test.txt

# -s 操作符测试目标文件是否存在且不为空
if [ -s $FILE ]
then
  # 如果操作符返回true,则echo命令会打印一条消息
    # 表明文件存在且不为空。
  echo "$FILE exists and is not empty"
else
  # 如果操作符返回false,则echo命令会打印一条消息
    # 表明文件要么不存在要么为空。
  echo "$FILE either does not exist or is empty"
  # 向目标文件添加文本
  echo "This is a test. This is not an empty file" > $FILE
fi

2. 现在,运行下面的命令来执行你的脚本(empty_file.sh)。

bash empty_file.sh

下面,你可以看到消息,说明test.txt要么不存在要么为空。但与此同时,脚本向test.txt文件添加了文本。

Executing the empty_file.sh file to test if the text.txt file is empty

3. 运行下面的cat命令来验证test.txt文件是否包含了添加的文本。

cat test.text
Verifying the text.txt file’s content

4. 最后,重新运行下面的bash命令来执行empty_file.sh脚本。

bash empty_file.sh

下面,你可以看到输出已经更改为test.txt存在且不为空,因为test.txt文件现在包含了一些文本并且大小大于零(0)。

Rerunning the empty_file.sh script to check if the test.txt file is empty

检查文件是否存在且可读

也许你的自动化涉及读取文件以执行任务。这些任务的成功将取决于文件是否可读。编写一个脚本来检查文件是否存在且可读将成为一个方便的解决方案。

为了演示检查文件是否存在且可读,请执行以下操作:

1. 运行以下命令以登录到另一个用户账户(ata)。

su - ata

您的提示符($)会更改,指示您已登录为其他用户。

Logging in to another user account

或者,您可以使用chmod命令更改文件的权限为可读、可写或两者兼有。

2. 登录后,使用您的文本编辑器创建一个名为readable_file.sh的新文件

将以下代码添加到readable_file.sh文件中,并保存更改。此代码检查/root目录中是否存在名为test.txt的文件,并且该文件是否可读。

#!/bin/bash
# 定义目标文件
FILE=test.txt

# 测试目标文件是否可读。
# 您可以将-r更改为-w以测试文件是否可写。
if [ -r $FILE ] 
then  
  # 如果运算符返回true,请打印一条消息说明
    # 文件存在且可读。
  echo "$FILE exists and is readable" 
else  
  # 如果运算符返回false,请打印一条消息说明
    # 文件不存在或不可读。
  echo "$FILE does not exist or is unreadable"
fi

3. 现在,运行以下命令以执行readable_file.sh脚本。

bash readable_file.sh

这次,您将看到一条消息,指出`/root/test.txt`不存在或不可读。由于text.test文件位于/root目录中,当前用户(ata)对text.txt文件没有读取权限。

Executing the readable_file.sh script

4. 最后,运行以下命令执行以下操作:

  • 更改sudoers文件,以允许当前用户(ata)使用sudo来运行提升的命令。
  • 执行`readable_file.sh`脚本,该脚本测试特定文件是否可读。
sudo bash
bash readable_file.sh

您可以看到下面的输出打印`test.txt`存在且可读,因为ata用户现在对test.txt文件有读取权限。

Changing the sudoers file and executing the readable_file.sh script

结论

A testing phase is always a priority before making drastic changes, whether on files or directories on your system. And in this tutorial, you’ve learned about the Bash file test operators and how to use them to test if a file (regular or special) or directory exists or if a file is readable or not.

有了这些新发现的技能,您可以自信地根据测试结果决定采取哪种行动。但是,还有许多其他方法可以使用Bash文件测试运算符。

为什么不尝试检查文件的扩展名?或者检查多个文件是否存在,以查看您需要的所有文件是否都可用?

Source:
https://adamtheautomator.com/bash-file-test/