如何在 Linux Bash 脚本中检查文件是否存在如何在 Linux Bash 脚本中检查文件是否存在如何在 Linux Bash 脚本中检查文件是否存在如何在 Linux Bash 脚本中检查文件是否存在
  • 文章
  • 正则表达式
    • 工具
  • 登录
找到的结果: {phrase} (显示: {results_count} 共: {results_count_total})
显示: {results_count} 共: {results_count_total}

加载更多搜索结果...

搜索范围
模糊匹配
搜索标题
搜索内容
发表 admin at 2025年2月28日
类别
  • 未分类
标签

如何在 Linux Bash 脚本中检查文件是否存在

如果 Linux Bash 脚本依赖于存在的某些文件或目录,它不能只是假设它们存在。它需要检查它们是否确实存在。以下是如何做到这一点。

不要假设任何事情

当您编写脚本时,您无法假设计算机上存在什么和不存在什么。如果脚本要在许多不同的计算机上分发和运行,那就更是如此了。迟早,脚本会在不符合你假设的计算机上运行,脚本会失败或运行不可预测。

我们在计算机上重视或创建的一切都存储在某种格式的文件中,所有这些文件都位于一个目录中。脚本可以读取、写入、重命名、删除和移动文件和目录——您可以在命令行上执行的所有操作。

作为人类,您的优势在于您可以看到目录的内容,并且知道文件是否存在——或者预期的目录是否存在。如果脚本在操作文件时出错,可能会产生严重的破坏性结果。

Bash 提供了一套全面的测试,您可以使用它们来检测文件和目录,并测试它们的许多属性。将这些合并到脚本中很容易,但在稳健性和精细控制方面的好处是相当可观的。

测试范围

通过将 if 语句与大量文件和目录测试中的适当测试相结合,我们可以轻松确定文件是否存在、是否可执行或可写等等。

  • -b:如果文件是块特殊文件则返回真。
  • -c:如果文件是特殊字符则返回真。
  • -d:如果“文件”是目录,则返回真。
  • -e:如果文件存在则返回真。
  • -f:如果文件存在且是常规文件,则返回真。
  • -g:如果文件具有 setgid 权限集 (chmod g+),则返回 true。
  • -h:如果文件是符号链接则返回真。
  • -L:如果文件是符号链接则返回真。
  • -k:如果设置了粘性位 (chmod +t),则返回 true。
  • -p:如果文件是命名管道则返回真。
  • -r:如果文件可读则返回真。
  • -s:如果文件存在并且不为空则返回真。
  • -S:如果文件是套接字则返回真。
  • -t:如果文件描述符在终端中打开,则返回 true。
  • -u:如果文件具有 setuid 权限集 (chmod u+),则返回 true。
  • -w:如果文件可写则返回真。
  • -x:如果文件可执行则返回真。
  • -O:如果 归您所有,则返回真。
  • -G:如果 归您的组所有,则返回真。
  • -N:如果文件自上次读取以来已被修改,则返回 true。
  • !:逻辑 NOT 运算符。
  • &&:逻辑与运算符。
  • ||:逻辑或运算符。

该列表以 -b 开头,因为 -a 测试已被弃用并被 -e 测试取代。

在脚本中使用测试

通用文件测试 if 语句是一个简单的脚本构造。双括号“[[ ]]”中的比较使用-f 测试来确定是否存在具有该名称的常规文件。

将此脚本的文本复制到编辑器中并将其保存到名为“script1.sh”的文件中,然后使用 chmod 使其可执行。

#!/bin/bash

if [[ -f $1 ]] 

then 

  echo "The file $1 exists." 

else 

  echo "The file $1 cannot be found." 

fi

您必须将文件名传递给命令行中的脚本。

chmod +x script1.sh

如果您想尝试本文中的其他示例,则需要对每个脚本执行此操作。

让我们在一个简单的文本文件上尝试脚本。

./script1.sh test-file.txt

该文件存在并且脚本正确地报告了这一事实。如果我们删除文件并重试,测试应该失败并且脚本应该向我们报告。

./script1.sh test-file.txt

在现实生活中,您的脚本需要采取任何适当的行动。也许它会标记错误并停止。也许它会创建文件并继续。它可能会从备份目录中复制一些内容来替换丢失的文件。这完全取决于脚本的目的。但至少现在脚本能够根据知道文件是否存在来做出决定。

-f 标志测试文件是否存在,是否为“常规”文件。换句话说,它不是看似文件但实际上不是的东西,例如设备文件。

我们将使用 ls 来验证“/dev/random”文件是否存在,然后查看脚本对它的构成。

ls -lh /dev/random
./script /dev/random

因为我们的脚本正在测试常规文件,而“/dev/random”是一个设备文件,所以测试失败。通常,要查明文件是否存在,您需要仔细选择要使用的测试,或者需要使用多个测试。

这是“script2.sh”,它测试常规文件和字符设备文件。

#!/bin/bash

if [[ -f $1 ]]
then
  echo "The file $1 exists."
else
  echo "The file $1 is missing or not a regular file."
fi

if [[ -c $1 ]]
then
  echo "The file $1 is a character device file."
else
  echo "The file $1 is missing or not a special file." 
fi

如果我们在“/dev/random”设备文件上运行这个脚本,第一个测试会失败,而第二个测试会成功。它将文件识别为设备文件。

./script2.sh /dev/random

实际上,它将它识别为一个字符设备文件。一些设备文件是块设备文件。就目前而言,我们的脚本无法处理这些。

./script2.sh /dev/sda

我们可以使用逻辑 OR 运算符并在第二个 if 语句中包含另一个测试。这次,无论文件是字符设备文件还是块设备文件,测试都将返回 true。这是“script3.sh”。

#!/bin/bash

if [[ -f $1 ]]
then
  echo "The file $1 exists."
else
  echo "The file $1 is missing or not a regular file."
fi

if [[ -c $1 || -b $1 ]]
then
  echo "The file $1 is a character or block device file."
else
  echo "The file $1 is missing or not a special file." 
fi

该脚本识别字符设备和块设备文件。

./script3.sh /dev/random
./script3.sh /dev/sda

如果区分不同类型的设备文件对您很重要,您可以使用嵌套的 if 语句。这是“script4.sh”。

#!/bin/bash

if [[ -f $1 ]]
then
  echo "The file $1 exists."
else
  echo "The file $1 is missing or not a regular file."
fi

if [[ -c $1 ]]
then
  echo "The file $1 is a character device file."
else
  if [[ -b $1 ]]
  then
    echo "The file $1 is a block device file." 
  else
    echo "The file $1 is missing or not a device file."
  fi
fi

此脚本识别并分类字符设备和块设备文件。

./script4.sh /dev/random
./script4.sh /dev/sda

使用逻辑 AND 运算符,我们可以一次测试多个特征。这是“script5.sh”。它检查文件是否存在并且脚本是否具有读取和它的写入权限。

#!/bin/bash

if [[ -f $1 && -r $1 && -w $1 ]]
then
  echo "The file $1 exists and we have read/write permissions."
else
  echo "The file $1 is missing, not a regular file, or we can't read/write to it."
fi

我们将在属于我们的文件和属于 root 的文件上运行脚本。

./script5.sh .bashrc
./script5.sh /etc/fstab

要测试目录是否存在,请使用 -d 测试。这是“script6.sh”。它是备份脚本的一部分。它做的第一件事是检查命令行传递的目录是否存在。它在 if 语句测试中使用逻辑 NOT 运算符 !。

#!/bin/bash

if [[ ! -d $1 ]]
then
  echo "Creating backup directory:" $1
  mkdir $1

  if [[ ! $? -eq 0 ]]
  then
    echo "Couldn't create backup directory:" $1
    exit
  fi
else
  echo "Backup directory exists."
fi

# continue with file backup
echo "Backing up to: "$1

如果该目录不存在,它会创建它。如果目录创建文件,则脚本退出。如果目录创建成功,或者目录已经存在,脚本将继续其备份操作。

我们将运行脚本,然后使用 ls 和 -d(目录)选项检查备份目录是否存在。

./script6.sh Documents/project-backup
ls -d Documents/project-backup

备份目录已创建。如果我们再次运行脚本,它应该报告目录已经存在。

./script6.sh

该脚本找到目录并继续执行备份。

测试,不要假设

迟早,假设会导致坏事发生。先测试,然后做出相应的反应。

知识就是力量。使用测试为您的脚本提供所需的知识。

©2015-2025 艾丽卡 support@alaica.com