Bash 使用双括号 [[ 和 sudo

Bash 使用双括号 [[ 和 sudo

我有一个命令,当以当前用户身份运行时可以运行,但如果我sudo在命令前面加上前缀,就会出现错误。

如果文件是目录,我会尝试删除它(但如果它是目录的符号链接,则不会删除它)。这很有效:

brad@ip-10-0-0-1:~$ [[ -d /path/to/my/place && ! -L /path/to/my/place ]] && rm -rf /path/to/my/place

但是,如果我尝试sudo以超级用户身份执行此操作,我会收到错误,因为sudo似乎认为[[是一个命令:

brad@ip-10-0-0-1:~$ sudo [[ -d /path/to/my/place && ! -L /path/to/my/place ]] && rm -rf /path/to/my/place
sudo: [[: command not found

我必须添加双括号才能使该! -L /path/to/my/place位工作;sudo以前我运行时,使用单括号就可以正常工作

brad@ip-10-0-0-1:~$ sudo [ -d /path/to/my/place ] && rm -rf /path/to/my/place

但是现在我试图检查以确保它不是符号链接,我无法让它工作sudo。我该怎么做:

  • sudo获取与或一起使用的双括号语法
  • 获取单括号语法允许我否定该-L部分?

答案1

$ type -a [
[ is a shell builtin
[ is /usr/bin/[
$ type -a [[
[[ is a shell keyword
$ 

如您所见[(除了是 shell 内置命令之外)是一个sudo可以使用的常规命令。[[不是。您需要bash提供[[

sudo bash -c '[[ -d /path/to/my/place && ! -L /path/to/my/place ]]' && …

因为[[是 shell 关键字,解析器会识别它并更改&&between[[和的行为]]。您不能使用&&inside,[ … ]因为它[充当命令,并且]实际上是传递给它的最后一个参数。使用&&inside 意味着有两个命令,这是错误的。

但是[支持-a,所以这可能工作:

sudo [ -d /path/to/my/place -a ! -L /path/to/my/place ] && …

但你应该避免这样做。来自本文

二进制-a-o[…] 是 POSIX 标准的 XSI 扩展。在 POSIX-2008 中,它们都被标记为过时。它们不应在新代码中使用。[ A = B -a C = D ](or ) 的一个实际问题是 POSIX 不指定带有超过 4 个参数的or命令-o的结果。它可能在大多数 shell 中都有效,但您不能指望它。如果您必须为 POSIX shell 编写,那么您应该使用由运算符分隔的两个or命令。test[test[&&

因此,如果您想使用,这应该更安全[

sudo [ -d /path/to/my/place ] && sudo [ ! -L /path/to/my/place ] && …

相关内容