根据我不允许评论的这个问题:
Is it necessary to specify traps other than EXIT?
恕我直言,这是一个不完整的答案,因为它没有涵盖通常的案例:TEMPDIR_OR_FILE=$(mktemp [ some switches and params and an XXX pattern] )
# ...so we want trap to do rm -rf ${TEMPDIR_OR_FILE}
给出的例子是:
# reset
trap 'excode=$?; cmd; trap - EXIT; echo $excode' EXIT HUP INT QUIT PIPE TERM
# ignore
trap 'excode=$?; trap "" EXIT; cmd; echo $excode' EXIT HUP INT QUIT PIPE TERM
此处的问题是,单引号会阻止您展开${TEMPDIR_OR_FILE}
我认为这是一个复杂因素是变量扩展的时间。我需要立即扩展${TEMPDIR_OR_FILE}
,但其他项可能需要等到陷阱执行。我该如何工作?
答案 0 :(得分:1)
你担心的代码,
trap 'EXIT' 'rm -f "$TEMPDIR_OR_FILE"'
... 确实有效;它只是在陷阱运行时查找TEMPDIR_OR_FILE
,而不是在它被定义时查找。这没有什么不妥:当陷阱运行时,最好时间来查看您的临时文件定义,因为这样您的脚本的其余部分可以在其中适当地更改这些定义执行。
请考虑以下事项:
declare -A tempfiles=( )
cleanup() { (( ${#tempfiles[@]} )) && rm -rf -- "${!tempfiles[@]}"; }
trap 'cleanup' EXIT
# ...do some stuff...
tempfiles[something]=$(mktemp -t -d something.XXXXXX)
echo "hello" >"${tempfiles[something]}/greeting"
# ...do more stuff...
tempfiles[something_else]=$(mktemp -t something_else.XXXXXX)
if [[ $keep_something_else ]]; then
# the user wants us to keep this temporary file! remove it from deletion list
unset tempfiles[keep_something_else]
fi
通过上述内容,您只需将清理功能定义为,并且当时不需要知道您的临时目录;当您退出时,您将查找列表,因为它存在然后。
在大多数情况下,在执行陷阱时,与在其定义时相比,扩展变量是合乎需要的。但是,你要求以另一种方式去做。
要安全地执行此操作 ,请使用printf %q
生成文件名的eval
- 安全版本,并在定义陷阱时将其展开为双引号。
printf -v tempdir_or_file_q '%q' "$TEMPDIR_OR_FILE"
trap 'retval=$?; rm -rf '"${tempdir_or_file_q}"'; exit "$retval"'
请注意,在引用要在定义时扩展的变量之前,我们结束初始单引号,用双引号展开它,结束那些双引号并在之后切换回单引号。