2017-10-13 65 views
0

根据这个问题我敢不允许评论:变量扩展的Bash陷阱?

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 

这里的问题是,单引号阻止你exp anding ${TEMPDIR_OR_FILE}

我认为这是一个复杂因素是变量扩大的时间。我需要${TEMPDIR_OR_FILE}立即展开,但其他项目可能需要等待陷阱执行。我如何完成这项工作?

+0

由于旁边所有大写名称用于具有对操作系统或系统有意义的变量,而具有至少一个小写字符的名称保留给应用程序使用,并且保证不会修改POSIX指定工具的行为。请参阅http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html第四段。 –

+0

这就是说,**为什么要在陷阱被定义时扩展TEMPDIR_OR_FILE,而不是执行它时?稍后在执行时执行此操作(通过将定义放在外部单引号内)可以让您更改正在使用的临时文件。 –

+1

根据我的经验,这不是一个问题。这些变量通常会设置一次,甚至可能只读,然后用于程序的其余部分。延期扩展不会改变任何内容。为什么你需要更快地解析它?我大概可以制定一个kludge,但不愿意增加维护头痛。 –

回答

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 

通过上述,您定义的清理功能只是一次,并不需要知道你当时的临时目录;当您退出时,您会查看该列表,因为它存在,然后


字面解释:扩大在定义时

在大多数情况下,这是可取的执行陷阱时展开变量,VS时,它的定义。但是,您要求以其他方式进行操作。

为此安全,使用printf %q来生成文件名的eval -safe版本,并定义陷阱时展开在双引号。

printf -v tempdir_or_file_q '%q' "$TEMPDIR_OR_FILE" 
trap 'retval=$?; rm -rf '"${tempdir_or_file_q}"'; exit "$retval"' 

请注意,我们引用您想在定义时展开,展开它在双引号,结束这些双引号和切换回单引号后的变量之前结束最初的单引号。