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


36

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

Answers:


23

不要在的输出上使用命令替换find。在这里,一切都可以用find

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

通过一些find实现(包括FreeBSD find来自和GNU find),您可以使用-delete代替-exec rm...

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

就像其他人所说的那样,您可以使用:(或for nothing in; do nothing; done)之类的noop命令或使用!关键字反转逻辑(在POSIX shell中可用,但在Bourne shell中不可用(您会发现使用:该操作在该shell中很常见))。mkshyash提供支持if false; then () else echo x; fi(我不会依赖它,因为将来的版本可能会改变)。

另一种方法是:

lsof... || {
  cmd1
  cmd2
}

虽然总的退出状态是一个差异,但lsof如果lsof失败则将是整体退出状态。


17
尽管这是执行@Novice User尝试的更好的方法,但它根本无法回答问题。
SeeJayBee 2014年

尽管-exec通常是有用的,但xargs有时是需要shell循环的。在这种情况下,while read name循环是首选选项(在GNU的bash中,您可以对两者都使用-0选项;可移植的是,您必须放弃换行符)。
Jan Hudec

@JanHudec,有很多方法可以移植。-print0-exec printf '%s\0' {} +(但可移植的是,除非您愿意考虑perl,否则您将无法处理该输出),并且通过find .//.进行一些后期处理,可以使换行xargs。请注意,它不是while read,而是while IFS= read -r
斯特凡Chazelas

@Chris,自从答案被接受以来,我已经为实际问题添加了答案。
斯特凡Chazelas

91

如果文件打开,您似乎想执行无操作操作,因此应在:其中添加一个,这是一个空命令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'


永远不会:陌生,它是bash-builtins中列出的第一个命令。
bolov 2015年

26

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

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

17

TL; DR

其他答案实际上都没有解决您原来的问题,即该命令为什么会出现语法错误。这是由thenelse之间缺少命令引起的。

失踪的命令

您的原始代码如下所示:

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

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

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

使用内置的Bourne修复语法

您可以通过在其他命令之前放置实际命令来解决此问题,但是注释本身不会起作用。的IF-THEN部分不能为空; 如果需要占位符,则可以使用内建冒号。例如:

$ if true; then :; else echo; fi

只需将其放置:thenelse之间的部分中,即可解决您遇到的语法错误。


1
Gnouc的答案,也是最受欢迎的一个,已经在解决原始问题。
jlliagre 2014年

只有答案可以解决语法错误。FWIW,您可以在行的开头用单个分号重现类似的错误。这将给人以强烈的暗示。 $ ; -bash: syntax error near unexpected token ';'
马修·汉尼根
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.