在'test'命令中使用多个条件

时间:2013-05-27 15:30:34

标签: bash shell

我一直在尝试将以下代码转换为使用'test'而不是'if'

if [ -e ./blah ] &&  [ ! -L ./blah ];
then
   exit 1
fi

我的意图是使用测试代替,这样我就不必明确地退出1。我正在尝试这样的事情:

test -e ./blah  && ! -L ./blah;

而不是&&,我尝试了-a,使用不同的支架组合,但我没有成功。我相信应该有一个简单的方法来做到这一点。任何人都可以帮助我吗?

7 个答案:

答案 0 :(得分:5)

test无法理解逻辑运算符&&||。您可以使用test -e ./blah -a ! -L ./blah,但如果您使用的是bash,则还可以切换到更强大的[[ .. ]]构造:

[[ -e ./blah && ! -L ./blah ]] 

答案 1 :(得分:2)

要使if [ -e ./blah ] && [ ! -L ./blah ];正常工作,请使用以下内容 if [ -e ./blah -a ! -L ./blah ];-a代表andhttp://tldp.org/LDP/abs/html/comparison-ops.html

演示 - http://ideone.com/GR8UiK

但是,正如其他人所指出的,[[ .. ]]构造比[...]更强大。

答案 2 :(得分:1)

你可以将它们全部组合起来(包括if if fi):

[[ -e ./blah && ! -L ./blah ]] && exit 1

答案 3 :(得分:1)

使用[[关键字,因为它更强大。

if [[ -e ./blah && ! -L ./blah ]]
    then
    ...
fi

但是,为了确保可移植性,你也可以做这样的事情

if [ -e ./blah ] && [ ! -L ./blah  ] 
    then
    ...do something
fi

答案 4 :(得分:1)

当您要求使用test时,您可以这样做:

test -e ./blah && test -L ./blah || ( echo 'First action' ; echo 'Second action )

不同的运算符(&&||等...)首先由shell解析,因此您无法在命令参数中使用它。

答案 5 :(得分:1)

if [ -e ./blah ] && [ ! -L ./blah ];

相当于

if test -e ./blah && test ! -L ./blah;

因此你可以简单地写

test -e ./blah && test ! -L ./blah

即便:

$ help [\[] | tail -n +3
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.

答案 6 :(得分:1)

执行以下操作:

$ ls -i /bin/test
54008404 /bin/test
$ ls -i /bin/[
54008404 /bin/test

54008404 inode 号码。这是文件的真实名称。 /bin/test只指向inodeinode包含所有文件信息。

需要注意的是/bin/[/bin/test是相同的 inode 。这意味着,他们是同一个命令。

因此:

if [ -f "$foo" ]

与:

相同
if test -f "$foo"

if命令执行给定的命令,然后如果命令返回true则执行if子句,如果命令为false则不执行该子句。

例如:

if grep -q "foo" $foo
then
    echo "File $foo contains the regular expression /foo/"
fi

完全有效。 grep -q命令(在grep的许多变体中意味着搜索正则表达式,如果该正则表达式在文件中,则返回退出代码0(这意味着命令成功)并且是真的。)

注意没有方括号。

test命令(或[...])仅按指定运行测试,如果测试为真,则返回退出代码0(因此命令成功) 。就是这样。

您可能还会看到此构造:

[ "$foo" = "$bar" ] && echo "$foo is equal to $bar"

&&表示如果第一个命令返回零退出代码,则执行下一个命令(并返回退出代码)。否则,只需返回第一个命令的退出代码。

因此:

if [ -e ./blah ] &&  [ ! -L ./blah ];

表示运行test -e ./blah并且如果为真(即文件存在)执行test ! -L ./blah,如果也是如此,则运行语句的if子句。 / p>

请注意,[ -e ./blah][ ! -L ./blah ]是两个单独的命令。 &&将两个命令组合在一起:

[ "$foo" = "$bar" ] && some_command;

这就是说,运行test "$foo" = "$bar"如果是,请运行命令some_command。请注意,这相当于:

if [ "$foo" = "$bar" ]
then
    some_command
fi

另一个列表结构是||。这意味着如果第一个命令成功,则返回退出代码0,并且不运行第二个命令。因此:

[ "$foo" = "$bar" ] || some_command;

与:

相同
if [ "$foo" = "$bar" ]
then
    :
else
     some_command
fi

让我们回到你原来的问题:

if [ -e ./blah ] &&  [ ! -L ./blah ];
then
   exit 1
fi

与:

相同
if test -e ./blah && test ! -L ./blah
then
    exit 1
fi

相同
test -e ./blah && test ! -L ./blah && exit 1

这意味着:如果test -e ./blah为真(./blah是文件),则在&&列表运算符后执行命令。这是test -! -L ./blah。如果此测试也为真,请再次在&&列表运算符后运行命令。

这也可以改写为:

test -e ./blah && test -L ./blah || exit 1

这表示如果test -e ./blah为真,请在&&列表运算符后运行命令。如果test -L ./blah为false,请在||运算符后运行命令。