Wil*_*ard 33 bash shell-script
我想在一个 shell if 语句中组合多个条件,并否定组合。对于条件的简单组合,我有以下工作代码:
if [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ; then
# do stuff with the files
fi
Run Code Online (Sandbox Code Playgroud)
这工作正常。如果我想否定它,我可以使用以下工作代码:
if ! ( [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ) ; then
echo "Error: You done goofed."
exit 1
fi
# do stuff with the files
Run Code Online (Sandbox Code Playgroud)
这也按预期工作。但是,我突然想到我不知道括号实际上在做什么。我想将它们仅用于分组,但它实际上是否产生了一个子外壳?(我怎么知道?)如果是这样,有没有办法在不产生子shell的情况下对条件进行分组?
cuo*_*glm 40
您需要使用{ list;}
代替(list)
:
if ! { [ -f file1 ] && [ -f file2 ] && [ -f file3 ]; }; then
: do something
fi
Run Code Online (Sandbox Code Playgroud)
它们都是Grouping Commands,但{ list;}
在当前 shell 环境中执行命令。
请注意,需要;
in{ list;}
将列表与}
反向词分隔,您也可以使用其他分隔符。后面的空格(或其他分隔符){
也是必需的。
zwo*_*wol 10
要在 shell 中可移植地否定复杂的条件,您必须要么应用德摩根定律并在[
调用中一直向下推否定...
if [ ! -f file1 ] || [ ! -f file2 ] || [ ! -f file3 ]
then
# do stuff
fi
Run Code Online (Sandbox Code Playgroud)
... 或者你必须使用then :; else
...
if [ -f file1 ] && [ -f file2 ] && [ -f file3 ]
then :
else
# do stuff
fi
Run Code Online (Sandbox Code Playgroud)
if ! command
不可移植,也不可移植[[
。
如果您不需要完全的可移植性,请不要编写 shell 脚本。实际上,与您相比,您在随机选择的 Unix 上更有可能找到。/usr/bin/perl
bash
您可以完全使用该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.
Run Code Online (Sandbox Code Playgroud)
所以你的情况可能看起来像:
if [ -f file1 -a -f file2 -a -f file3 ] ; then
# do stuff with the files
fi
Run Code Online (Sandbox Code Playgroud)
为了否定使用转义括号:
if [ ! \( -f file1 -a -f file2 -a -f file3 \) ] ; then
echo "Error: You done goofed."
exit 1
fi
# do stuff with the files
Run Code Online (Sandbox Code Playgroud)
其他人已经注意到{
复合命令;}
分组,但如果您在一组上执行相同的测试,您可能希望使用不同的类型:
if ! for f in file1 file2 file3
do [ -f "$f" ] || ! break
done
then : do stuff
fi
Run Code Online (Sandbox Code Playgroud)
...正如在其他地方用 演示的那样{ :;}
,嵌套复合命令没有任何困难......
请注意,上述(通常)测试常规文件。如果你正在寻找只为现有的,可读的文件,这是不是目录:
if ! for f in file1 file2 file3
do [ ! -d "$f" ] &&
[ -r "$f" ] || ! break
done
then : do stuff
fi
Run Code Online (Sandbox Code Playgroud)
如果您不在乎它们是否是目录:
if ! command <file1 <file2 <file3
then : do stuff
fi
Run Code Online (Sandbox Code Playgroud)
...适用于任何可读、可访问的文件,但可能会挂起没有作者的 fifos。