为什么在空字符串上使用 -d 检查文件夹是否存在会返回 true?

Moa*_*sry 8 bash

我正在写一些脚本并写了一些类似的东西

ARTIFACTS="/SOME/PATH"
[ -d $ARTIFCATS ] && rm -rf $ARTIFACTS/*
Run Code Online (Sandbox Code Playgroud)

发生的事情是出于愚蠢,我没有执行第一行就执行了第二行。原来 [ -d "" ] 返回真,表达式变成了

rm -rf /*
Run Code Online (Sandbox Code Playgroud)

幸运的是它只是一台测试机,我不是sudo,但虽然我丢失了一些数据

我的问题是,为什么 [ -d "" ] 返回 true?文档清楚地说明它检查路径是否存在并且是一个文件夹

我通过使用解决了这个问题

[ -e $ARTIFACTS ]
这似乎有效

干杯

mpy*_*mpy 9

1. 这两个测试返回true

# [ -d ] && echo true || echo false
true
# [ -d $SOME_UNSET_VAR ] && echo true || echo false
true
Run Code Online (Sandbox Code Playgroud)

根据 POSIX(如@Tim 所述)。

2.但这会返回false(问题中所述 正确

# [ -d "" ] && echo true || echo false
false
Run Code Online (Sandbox Code Playgroud)

因为test使用两个参数调用(尽管第二个参数是空字符串)。

3. 这就是为什么最好使用( )[[ … ]]而不是test( [ … ]) 的原因,大多数(所有?)当前的 shell 都提供了。此构造检查您是否提供了足够的参数(否则会引发错误并中止)

# [[ -d ]] && echo true || echo false
bash: unexpected argument `]]' to conditional unary operator
bash: syntax error near `]]'
Run Code Online (Sandbox Code Playgroud)

或者只是表现得像人们期望的那样:

# [[ -d $SOME_UNSET_VAR ]] && echo true || echo false
false
Run Code Online (Sandbox Code Playgroud)

4. 而且,正如@Gilles 所指出的,更重要的是双引号替换。因此-d "$SOME_UNSET_VAR"扩展为-d ""并返回false甚至test(等于情况 2)。因此,这也与 Bourne shell 兼容sh

# [ -d "$SOME_UNSET_VAR" ] && echo true || echo false
false
Run Code Online (Sandbox Code Playgroud)

使用 bash 3.00.16(1) 和 4.1.5(1) 测试


Tim*_*Tim 6

这个问题已经在 StackOverflow 上得到了回答。它表示,根据 POSIX 标准,test如果只使用一个非空参数(并且没有其他参数)调用它,则应始终返回成功。

这也应该是这种情况test -e(实际上它在我的系统上),所以要小心。

而是使用:

[ -d "$ARTIFACTS" ]
Run Code Online (Sandbox Code Playgroud)

test 即使变量为空,也会使用两个参数调用,并在这种情况下返回 false。


dev*_*ull 4

我通过使用 [ -e $ARTIFACTS ] 解决了这个问题,这似乎有效

错了。它起作用是因为$ARTIFACTS现在设置了一些东西。

当未设置变量时,则说

[ -d $SOMEVAR ]
Run Code Online (Sandbox Code Playgroud)

或者

[ -e $SOMEVAR ]
Run Code Online (Sandbox Code Playgroud)

都会评估为,因为true这意味着说

[ -d ]
Run Code Online (Sandbox Code Playgroud)

[ -e ]
Run Code Online (Sandbox Code Playgroud)

分别。(说[ foobar ]总是评估为真。)

话说

set -u
Run Code Online (Sandbox Code Playgroud)

在这种情况下会派上用场。 help set会告诉你:

  -u  Treat unset variables as an error when substituting.
Run Code Online (Sandbox Code Playgroud)

  • 啊废话 [ -e $ARTIFACTS ] 带有空工件会产生 [ -e ] 而不是 [ -e "" ],明白了 (2认同)