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 ';'