为什么以下脚本不执行,但给出语法错误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
只需放入:
之间的部分然后和别的将修复您遇到的语法错误。