用bash函数修饰命令

  • 本文关键字:命令 函数 bash bash
  • 更新时间 :
  • 英文 :


我想装饰一些命令(condamamba在我的情况下),但不是所有命令(所以不像这个Stack Exchange帖子中描述的那样)。

由于这个Stack Exchange答案,我设法为conda命令做到了这一点,但不是为mamba命令,通过在我的~/.bashrc中放入以下内容:

decorate () {
# From https://unix.stackexchange.com/a/125853/457538
eval "_inner_$(typeset -f $1)"
eval "
$1 () {
echo "BEFORE"
_inner_$1 $@
local ret=$?
echo "AFTER"
return $ret
}
"
}
decorate conda
decorate mamba

它适用于conda而不适用于mamba,因为此实现依赖于typeset -f $1以新名称(_inner_$1)重新复制修饰函数并覆盖原始名称,并且这(typeset -f $1)仅适用于实际的bash函数(conda是一个),而不适用于二进制(mamba是)。

对于mamba,typeset -f $1没有返回任何内容,因此当我source ~/.bashrc时,我从eval "_inner_$(typeset -f $1)"

行得到以下错误
_inner_: command not found

当我尝试使用装饰的mamba时,我得到:

~$ mamba
BEFORE
_inner_mamba: command not found
AFTER

所以,我找不到一种通过bash函数修饰二进制命令的方法,我对这个问题的通用解决方案感兴趣。

然而,如果这很重要,我现在的真正目标是在condamamba执行期间临时修改umask,然后,如果有针对这种特定情况的替代方法,我也会采用它。

有两个路径-一个用于功能,一个用于命令。记住引用参数——总是引用变量展开。记住引号-你对"引号的使用是奇怪的,保持一致。简化的概念证明:

decorate () {
if [[ -n "$(typeset -f "$1")" ]]; then
# From https://unix.stackexchange.com/a/125853/457538
eval "_inner_$(typeset -f $1)"
eval "
$1 () {

echo "BEFORE"
_inner_$1 "$@"
local ret=$?
echo "AFTER"
return $ret
}
"
else
eval "
$1 () {

echo "BEFORE"
command $1 "$@"
local ret=$?
echo "AFTER"
return $ret
}
"
fi
}

注意你的命令是非常不安全的-decorate 'rm -r / ; func'将在eval内执行并删除所有文件。一定要防止这样的错误。