如何一起使用 bash 的 if test 和 find 命令?

cwd*_*cwd 30 scripting bash find shell-script test

我有一个包含崩溃日志的目录,我想在基于 find 命令的 bash 脚本中使用条件语句。

日志文件以这种格式存储:

/var/log/crashes/app-2012-08-28.log
/var/log/crashes/otherapp-2012-08-28.log
Run Code Online (Sandbox Code Playgroud)

我希望 if 语句仅在特定应用程序的崩溃日志在过去 5 分钟内被修改时才返回 true。find我会使用的命令是:

find /var/log/crashes -name app-\*\.log -mmin -5
Run Code Online (Sandbox Code Playgroud)

我不确定如何将其if正确地合并到声明中。我认为这可能有效:

if [ test `find /var/log/crashes -name app-\*\.log -mmin -5` ] then
 service myapp restart
fi
Run Code Online (Sandbox Code Playgroud)

有几个地方我不清楚:

  • 我查看了if 标志,但我不确定应该使用哪一个(如果有)。
  • 我是否需要该test指令,还是应该直接针对 find 命令的结果进行处理,或者可能用于find... | wc -l获取行数?
  • 不是 100% 有必要回答这个问题,而是test为了测试命令返回的返回码?而且它们有点不可见 - 在stdout/之外stderr?我阅读了该man页面,但我仍然不清楚何时使用test以及如何调试它。

mrb*_*mrb 32

[andtest是同义词(除了[requires ]),所以你不想使用[ test

[ -x /bin/cat ] && echo 'cat is executable'
test -x /bin/cat && echo 'cat is executable'
Run Code Online (Sandbox Code Playgroud)

test如果条件为真,则返回零退出状态,否则非零。这实际上可以被任何程序替换以检查其退出状态,其中 0 表示成功,非零表示失败:

# echoes "command succeeded" because echo rarely fails
if /bin/echo hi; then echo 'command succeeded'; else echo 'command failed'; fi

# echoes "command failed" because rmdir requires an argument
if /bin/rmdir; then echo 'command succeeded'; else echo 'command failed'; fi
Run Code Online (Sandbox Code Playgroud)

但是,以上所有示例仅针对程序的退出状态进行测试,而忽略了程序的输出。

对于find,您需要测试是否生成了任何输出。-n测试非空字符串:

if [[ -n $(find /var/log/crashes -name "app-*.log" -mmin -5) ]]
then
    service myapp restart
fi
Run Code Online (Sandbox Code Playgroud)

通过help testbash命令行调用,可以获得完整的测试参数列表。

如果您正在使用bash(而不是sh),您可以使用[[ condition ]],当您的条件中有空格或其他特殊情况时,它的行为更可预测。否则它通常与使用相同[ condition ]。我[[ condition ]]在这个例子中使用过,因为我尽可能这样做。

我也改变`command`$(command),这也通常表现类似,但是具有嵌套命令更好。


ang*_*gus 10

find如果没有任何错误,它将成功退出,因此您不能指望它的退出状态来知道它是否找到了任何文件。但是,正如您所说,您可以计算找到的文件数量并测试该数字。

它会是这样的:

if [ $(find /var/log/crashes -name 'app-*.log' -mmin -5 | wc -l) -gt 0 ]; then
    ...
fi
Run Code Online (Sandbox Code Playgroud)

test(aka [) 不检查命令的错误代码,它有一个特殊的语法来进行测试,如果测试成功,则以错误代码 0 退出,否则为 1。它会if检查您传递给它的命令的错误代码,并根据它执行其主体。

请参阅man test(或help test,如果您使用bash)和help if(同上)。

在这种情况下,wc -l将输出一个数字。我们使用test's 选项-gt来测试该数字是否大于0。如果是,test(或[)将返回退出代码0if会将该退出代码解释为成功,并将在其主体内运行该代码。