2013-05-27 56 views
1

我一直在尝试转换下面的代码中使用“测试”,而不是“如果”使用多个条件“测试”命令

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

我的本意是用测试来代替,让我没有明确地退出1。我想是这样的:

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

,而不是& &,我已经试过-a,用不同的支架的组合,但我没有成功。我相信应该有一个简单的方法来做到这一点。谁能帮我 ?

回答

5

test不理解逻辑运算符&&||。您可以使用test -e ./blah -a ! -L ./blah,但如果你使用bash,您还可以切换到它的功能更强大[[ .. ]]结构:

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

您可以将它们全部(包括如果再FI):

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

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

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

但是,为了保证便携性,你可以做这样的事情太

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

至于你问到使用test,你可以做像这样:

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

不同的运营商(&&||等)首先由shell解析,所以你不能在命令参数中使用它。

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 `['. 
1

执行以下操作:

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

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

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

因此:

if [ -f "$foo" ] 

相同:

if test -f "$foo" 

if命令执行给出的命令,然后将执行if子句如果该命令将返回真并且不执行该子句如果命令它是假的。

例如:

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条款。

请注意,[ -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 

让我们回到你的_original问题:

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

是一样的:

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

哪个与

0123相同
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为假,请在||运算符后面运行命令。