Answers:
不要在的输出上使用命令替换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会这样做。yash并zsh没有这个限制(if false; then else echo x; fi甚至if false; then else fi可以和他们一起工作)。
就像其他人所说的那样,您可以使用:(或for nothing in; do nothing; done)之类的noop命令或使用!关键字反转逻辑(在POSIX shell中可用,但在Bourne shell中不可用(您会发现使用:该操作在该shell中很常见))。mksh并yash提供支持if false; then () else echo x; fi(我不会依赖它,因为将来的版本可能会改变)。
另一种方法是:
lsof... || {
cmd1
cmd2
}
虽然总的退出状态是一个差异,但lsof如果lsof失败则将是整体退出状态。
-exec通常是有用的,但xargs有时是需要shell循环的。在这种情况下,while read name循环是首选选项(在GNU的bash中,您可以对两者都使用-0选项;可移植的是,您必须放弃换行符)。
-print0是-exec printf '%s\0' {} +(但可移植的是,除非您愿意考虑perl,否则您将无法处理该输出),并且通过find .//.进行一些后期处理,可以使换行xargs。请注意,它不是while read,而是while IFS= read -r。
如果文件打开,您似乎想执行无操作操作,因此应在:其中添加一个,这是一个空命令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中列出的第一个命令。
其他答案实际上都没有解决您原来的问题,即该命令为什么会出现语法错误。这是由then和else之间缺少命令引起的。
您的原始代码如下所示:
if lsof "$filename" > /dev/null
then
# file is open
else
echo "deleting $filename"
rm "$filename"
fi
问题是您在then和else之间有注释,但是注释没有被视为命令。简而言之,您可以按照以下方式(结构上)重写您遇到的问题:
$ if true; then else echo; fi
bash: syntax error near unexpected token `else'
您可以通过在其他命令之前放置实际命令来解决此问题,但是注释本身不会起作用。的IF-THEN部分不能为空; 如果需要占位符,则可以使用内建的冒号。例如:
$ if true; then :; else echo; fi
只需将其放置:在then和else之间的部分中,即可解决您遇到的语法错误。
$ ; -bash: syntax error near unexpected token ';'