我在写一些脚本,写了类似的东西
ARTIFACTS="/SOME/PATH"
[ -d $ARTIFCATS ] && rm -rf $ARTIFACTS/*
发生的事情是,出于愚蠢,我执行了第二行而没有执行第一行。结果发现 [ -d "" ] 返回 true,表达式变成了
rm -rf /*
幸运的是,这只是一台测试机,而且我不是 sudo,尽管我丢失了一些数据
我的问题是,为什么 [ -d "" ] 返回 true?文档明确指出它检查路径是否存在并且是否为文件夹
我通过使用解决了这个问题
[ -e $ARTIFACTS ]
这似乎有效
干杯
答案1
1. 这两个测试返回真的:
# [ -d ] && echo true || echo false
true
# [ -d $SOME_UNSET_VAR ] && echo true || echo false
true
根据 POSIX(如@Tim 所解释)。
2. 但这也错误的(不是 真的如问题所述)
# [ -d "" ] && echo true || echo false
false
因为test
调用时有两个参数(尽管第二个参数是空字符串)。
3. 这就是为什么最好使用( )[[ … ]]
而不是( ),因为大多数(所有?)当前 shell 都提供该功能。此构造会检查您是否提供了足够的参数(否则会引发错误并中止)test
[ … ]
# [[ -d ]] && echo true || echo false
bash: unexpected argument `]]' to conditional unary operator
bash: syntax error near `]]'
或者只是表现得像人们期望的那样:
# [[ -d $SOME_UNSET_VAR ]] && echo true || echo false
false
4. 而且,正如@Gilles 指出的那样,更重要的是对替换进行双引号处理。因此-d "$SOME_UNSET_VAR"
扩展为-d ""
并返回错误的甚至与test
(等于情况 2)。因此这也与 Bourne shell 兼容sh
:
# [ -d "$SOME_UNSET_VAR" ] && echo true || echo false
false
已使用 bash 3.00.16(1) 和 4.1.5(1) 进行测试
答案2
这个问题已经已回答在 StackOverflow 上。它表示,根据 POSIX 标准,test
如果使用一个非空参数(并且没有其他参数)调用它,则应该始终返回成功。
这也应该是这种情况test -e
(事实上在我的系统上也是如此),所以要小心。
改为使用:
[ -d "$ARTIFACTS" ]
test
即使变量为空,也会使用两个参数进行调用,在这种情况下返回 false。
答案3
我通过使用 [ -e $ARTIFACTS ] 解决了这个问题,这似乎有效
你是错误的。它起作用是因为$ARTIFACTS
现在设置为了某样东西。
当变量未设置时,则说
[ -d $SOMEVAR ]
或者
[ -e $SOMEVAR ]
会两个都评估为,true
因为它意味着说
[ -d ]
和
[ -e ]
分别。(说[ foobar ]
总是会被评估为真。)
说
set -u
在这种情况下很有用。 help set
会告诉你:
-u Treat unset variables as an error when substituting.
答案4
看到您设置了变量 ARTIFACTS,并且正在检查 ARTIFCATS。可能是输入错误?
无论如何,-d 和 -e 都会对未设置的变量产生相同的结果。
因此使用双引号它会帮助你。
ARTIFACTS="/SOME/PATH"
[ -d "$ARTIFACTS" ] && rm -rf -- "$ARTIFACTS/"*
注意:如果您的“/SOME/PATH”中有任何带空格的文件夹,您提到的脚本将会中断,并出现“预期二元运算符”错误。
例子:
ARTIFACTS="/home backup/"
1) [ -d $ARTIFACTS ] && rm -rf $ARTIFACTS/*
bash: [: /home: binary operator expected
2) [ -d "$ARTIFACTS" ] && rm -rf "$ARTIFACTS"/*
会很好。不要忘记在rm
调用中也加上引号(rm -rf $ARTIFACTS
会愉快地删除/home
然后抱怨backup/*
不存在)。
此外,包括-L
检查将确保它是一个目录,而不仅仅是目录的符号链接。
所以,基本上,
[ -d "$ARTIFACTS" && ! -L "$ARTIFACTS" ] && rm -rf -- "$ARTIFACTS"/*