bash if 不是没有子 shell 的多个条件?

bash if 不是没有子 shell 的多个条件?

我想在 shell if 语句中组合多个条件,并否定该组合。我有以下用于简单条件组合的工作代码:

if [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ; then
  # do stuff with the files
fi

这很好用。如果我想否定它,我可以使用以下工作代码:

if ! ( [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ) ; then
  echo "Error: You done goofed."
  exit 1
fi
# do stuff with the files

这也按预期工作。然而,我发现我不知道括号实际上在做什么。我仅将它们用于分组,但它实际上会生成子shell吗? (我怎么知道?)如果是这样,有没有办法在不生成子 shell 的情况下对条件进行分组?

答案1

您需要使用{ list;}而不是(list)

if ! { [ -f file1 ] && [ -f file2 ] && [ -f file3 ]; }; then
  : do something
fi

他们俩都是分组命令,但{ list;}在当前 shell 环境中执行命令。

请注意,需要;in{ list;}来分隔列表和}反向单词,您也可以使用其他分隔符。后面的空格(或其他分隔符){也是必需的。

答案2

便携式的在 shell 中否定复杂条件,您必须应用德摩根定律并将否定一直推到[调用中......

if [ ! -f file1 ] || [ ! -f file2 ] || [ ! -f file3 ]
then
    # do stuff
fi

...或者你必须使用then :; else...

if [ -f file1 ] && [ -f file2 ] && [ -f file3 ]
then :
else
  # do stuff
fi

if ! command不是可移植的,也不是[[

如果您不需要完全的便携性,不要写 shell 脚本。你其实是更多的/usr/bin/perl很可能会在随机选择的 Unix 上找到比你还多的人bash

答案3

您可以完全使用此test功能来实现您想要的功能。从手册页test

 ! expression  True if expression is false.
 expression1 -a expression2
               True if both expression1 and expression2 are true.
 expression1 -o expression2
               True if either expression1 or expression2 are true.
 (expression)  True if expression is true.

所以你的情况可能是这样的:

if [ -f file1 -a -f file2 -a -f file3 ] ; then
    # do stuff with the files
fi

对于否定,请使用转义括号:

if [ ! \( -f file1 -a -f file2 -a -f file3 \) ] ; then
    echo "Error: You done goofed."
    exit 1
fi
# do stuff with the files

答案4

这不是对您主要问题的完整答案,但我注意到您在评论中提到了复合测试(可读文件);例如,

if [ -f file1 ] && [ -r file1 ] && [ -f file2 ] && [ -r file2 ] && [ -f file3 ] && [ -r file3 ]

您可以通过定义 shell 函数来稍微巩固这一点;例如,

readable_file()
{
    [ -f "$1" ]  &&  [ -r "$1" ]
}

将错误处理添加到(例如,[ $# = 1 ])以适应口味。上面的第一条if语句现在可以压缩为

if readable_file file1  &&  readable_file file2  &&  readable_file file3

您可以通过缩短函数名称来进一步缩短它。同样,您可以定义not_readable_file()(或nrf简称)并在函数中包含否定。

相关内容