当“else”跟在空的“then”子句之后时出现 Bash 语法错误

Nov*_*ser 44 shell shell-script

为什么下面的脚本不会执行,而是给出一个语法错误else

LOGS3_DIR=~/logs
if [ -d "$LOGS3_DIR" ]; then
 cd
 cd "$LOGS3_DIR"
 echo "$LOGS3_DIR"
 for filename in `find "." -mtime 1 -type f`
  do
  if lsof "$filename" > /dev/null
  then
    # file is open
  else
    echo "deleting $filename"
    rm "$filename"
  fi
 done
fi
Run Code Online (Sandbox Code Playgroud)

cuo*_*glm 109

如果文件已打开,您似乎想执行无操作,因此您应该添加一个:,它是 中的一个空命令bash

if lsof "$filename" > /dev/null; then
  # file is open
  :
else
  printf 'deleting %s\n' "$filename"
  rm -- "$filename"
fi
Run Code Online (Sandbox Code Playgroud)

如果您不使用:bash则无法解析您的代码,并且会显示类似bash: syntax error near unexpected token 'else'.

  • `:` 从来都不是新的,它是 bash-builtins 中列出的第一个命令。 (3认同)

Jos*_* R. 27

另一种选择:颠倒你的逻辑。

if ! lsof "$filename" >/dev/null;then
    echo "deleting $filename"
    rm "$filename"
fi
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 24

不要在find. 在这里,一切都可以通过find

find . -mtime 1 -type f ! -exec lsof -t {} \; -exec rm -f {} \; > /dev/null
Run Code Online (Sandbox Code Playgroud)

随着一些find实现(包括FreeBSDfind来自何方和GNU find),你可以使用-delete的替代-exec rm...

您收到错误的原因是,在then和之间没有命令,else并且某些 shell(从该语法来自的 Bourne shell 开始)需要至少一个(并且注释不是命令)。请注意,这完全是任意的,并且没有理由为什么这些 shell 会这样做。yash并且zsh没有那个限制(if false; then else echo x; fi甚至if false; then else fi可以与它们一起工作)。

正如其他人所说,您可以使用像:(or for nothing in; do nothing; done)这样的 noop 命令或使用!关键字反转逻辑(在 POSIX shell 中可用,但在 Bourne shell 中不可用(您会发现:在该 shell中使用for that 很常见))。mksh并且yash碰巧支持if false; then () else echo x; fi(我不会依赖它,因为这可能会在未来的版本中改变)。

另一种方法是:

lsof... || {
  cmd1
  cmd2
}
Run Code Online (Sandbox Code Playgroud)

虽然一个区别是整体退出状态,这将是lsofiflsof失败。

  • 虽然这是做@Novice 用户尝试的更好的方法,但它根本没有回答问题。 (21认同)

Cod*_*ome 19

TL; 博士

其他答案都没有真正解决您最初的问题,即为什么命令会出现语法错误。这是由thenelse之间缺少命令引起的。

丢失的命令

您的原始代码如下所示:

if lsof "$filename" > /dev/null
then
  # file is open
else
  echo "deleting $filename"
  rm "$filename"
fi
Run Code Online (Sandbox Code Playgroud)

问题是您在thenelse之间有一个注释,但该注释不被视为命令。简而言之,您可以按如下方式重写您遇到的问题(从结构上讲):

$ if true; then else echo; fi
bash: syntax error near unexpected token `else'
Run Code Online (Sandbox Code Playgroud)

使用 Bourne 内置函数修复您的语法

您可以通过在else之前放置实际命令来解决此问题,但单独添加注释是行不通的。的IF-THEN部分不能为空; 如果你想要一个占位符,你可以使用内置冒号。例如:

$ if true; then :; else echo; fi
Run Code Online (Sandbox Code Playgroud)

只需放入thenelse:之间的部分即可修复您遇到的语法错误。

  • Gnouc 的回答,也是最受好评的回答,已经在解决最初的问题。 (2认同)