Bash 复合条件,带通配符和文件存在检查

标签 bash file shell grep conditional-statements

我已经掌握了 Bash 复合条件的基础知识,并阅读了几种不同的方法来检查通配 rune 件是否存在,但我无法理解这个,所以我想我会寻求帮助...

我需要: 1.) 检查是否存在一些匹配模式的文件 和 2.) 检查不同文件中的文本是否存在。

我知道有很多方法可以做到这一点,但我真的没有知识来确定它们的优先级(如果您有这些知识,我也有兴趣阅读相关内容)。

首先想到的是对 #1 使用 find,对 #2 使用 grep

有点像

if [ `grep -q "OUTPUT FILE AT STEP 1000" ../log/minimize.log` ] \
      && [ `find -name "jobscript_minim\*cmd\*o\*"` ]; then
   echo "Both passed! (1)"
fi

虽然奇怪,但失败了:

if `grep -q "OUTPUT FILE AT STEP 1000" ../log/minimize.log` ;then
   echo "Text passed!"
fi
if `find -name "jobscript_minim\*cmd\*o\*"` ;then
   echo "File passed!"
fi

都通过了...

我读了一些书,看到有人在谈论多个文件名在 if 语句中匹配通配符的问题。最好的解决方案是什么? (在回答我的问题时,我假设您在此过程中也对这个问题有所了解)

有什么想法/解决方案/建议吗?

最佳答案

让我们先解决您尝试失败的原因:

if [ `grep -q …` ]; 

这会在反引号之间运行 grep 命令,并在条件命令中插入输出。由于 grep -q 不产生任何输出,就好像您编写了 if [ ];

条件语句应该测试 grep 的返回码,而不是它的输出。因此它应该简单地写成

if grep -q …;

find 命令返回 0(即 true),即使它什么也没找到,所以这个技术不会起作用。有效的方法是通过收集其输出并将其与空字符串进行比较来测试其输出是否为空:

if [ "$(find …)" != "" ];

(等效测试是 if [ -n "$(find …)"]。)

这里注意两件事:

  • 我使用了 $(…) 而不是反引号。它们是等价的,除了反引号需要在它们内部使用奇怪的引号(尤其是当您尝试嵌套它们时),而 $(...) 简单可靠。只需使用 $(...) 并忘记反引号(除非您需要在双引号内编写 \`)。

  • $(…) 有双引号。这真的很重要。如果没有引号,shell 会将 find 命令的输出分解为单词。例如,如果 find 打印两行 dir/filedir/otherfile,我们需要 if [ "dir/file dir/otherfile"= ""]; 被执行,而不是 if [ dir/file dir/otherfile = ""]; 这是一个语法错误。这是 shell 编程的一般规则:始终在变量或命令替换周围加上双引号。 (变量替换为 $foo${foo};命令替换为 $(command)。)

    <

现在让我们看看您的要求。

  1. 检查是否存在匹配模式的文件

    如果您要递归地在当前目录或其下的任何目录中查找文件,那么 find -name "PATTERN" 是正确的。但是,如果目录树变大,效率就会很低,因为当我们只关心一个匹配项时,它可能会花费大量时间来打印所有匹配项。一个简单的优化是通过管道输入 head -n 1 只保留第一行; find 将在意识到 head 不再对它要说的内容感兴趣时停止搜索。

    if [ "$(find -name "jobscript_minimcmdo"| head -n 1)"!= ""];

    (请注意,双引号已经保护通配符不被扩展。)

    如果您只在当前目录中查找文件,假设您有 GNU find(在 Linux、Cygwin 和 Gnuwin32 上就是这种情况),一个简单的解决方案是告诉它不要递归到比当前目录更深的地方。

    if [ "$(find -maxdepth 1 -name "jobscript_minim*cmd*o*")"!= ""];

    还有其他更便携的解决方案,但编写起来更复杂。

  2. 检查不同文件中的文本是否存在。

    您已经获得了正确的 grep 命令。请注意,如果要搜索文字字符串,应使用 grep -F;如果您正在寻找正则表达式,grep -E 的语法比普通的 grep 更清晰。

综合起来:

if grep -q -F "OUTPUT FILE AT STEP 1000" ../log/minimize.log &&
   [ "$(find -name "jobscript_minim*cmd*o*")" != "" ]; then
  echo "Both passed! (1)"
fi

关于Bash 复合条件,带通配符和文件存在检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3561326/

相关文章:

bash - 如果 grep 找到它要查找的内容,则执行 X else Y

bash - zsh 或 bash 是否有方便英文文本的引号?

bash - Vim 从 bash 脚本运行命令并退出而不会使 shell 处于错误状态

ios - 在免费和付费应用程序之间共享文件

linux - 如何在 SED 或 AWK 中使用 if, else?

shell - 如何用awk打印 float

arrays - 从两个文件中读取变量并以模式输出到第三个文件

python - 如果注释行与我的 input.txt 文件中的 python 位于同一行代码中,则注释行不会被转义

java - 我试图打印的数字不断在下一行中相加

linux - 在 linux 中有 2 个阻塞脚本相互交互