当“else”跟随空的“then”子句时,Bash 语法错误

当“else”跟随空的“then”子句时,Bash 语法错误

为什么以下脚本不执行,但给出语法错误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

答案1

看来你想做一个无操作如果文件已打开,那么您应该添加一个:,这是一个空命令bash

if lsof "$filename" > /dev/null; then
  # file is open
  :
else
  printf 'deleting %s\n' "$filename"
  rm -- "$filename"
fi

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

答案2

另一种选择:扭转你的逻辑。

if ! lsof "$filename" >/dev/null;then
    echo "deleting $filename"
    rm "$filename"
fi

答案3

不要对输出使用命令替换find。在这里,一切都可以通过以下方式完成find

find . -mtime 1 -type f ! -exec lsof -t {} \; -exec rm -f {} \; > /dev/null

通过一些find实现(包括find它的来源 FreeBSD 和 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与它们一起正常工作)。

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

另一种方法是:

lsof... || {
  cmd1
  cmd2
}

尽管其中一个区别是整体退出状态,即失败lsof时的退出状态lsof

答案4

长话短说

其他答案都没有真正解决您最初的问题:为什么命令给出语法错误。这是由于之间缺少命令引起的然后别的

缺失的命令

你的原始代码如下所示:

if lsof "$filename" > /dev/null
then
  # file is open
else
  echo "deleting $filename"
  rm "$filename"
fi

问题是您之间有评论然后别的,但注释不被视为命令。简而言之,您可以将您遇到的问题(从结构上来说)重写如下:

$ if true; then else echo; fi
bash: syntax error near unexpected token `else'

使用 Bourne 内置程序修复语法

您可以通过在之前放置实际命令来解决此问题别的,但注释本身是不行的。这如果-那么部分不能为空;如果你想要占位符,你可以使用内置冒号。例如:

$ if true; then :; else echo; fi

只需放入:之间的部分然后别的将修复您遇到的语法错误。

相关内容