在没有用户配置的情况下运行 bash,同时仍然能够设置绑定

在没有用户配置的情况下运行 bash,同时仍然能够设置绑定

我希望能够运行具有以下两个属性的脚本

  1. 脚本中的所有内容都会运行,就像从未获取过 bashrc 一样。
  2. 我仍然可以设置脚本完成后保留的绑定。

例如,如果我的 .bashrc 看起来像

alias rm="echo don't use me"

我希望能够运行以下脚本

  • rm.me已移除
  • 之后,运行fn会回显i am bound
rm rm.me
fn() { echo i am bound; }

如果我运行bash my-script.sh,则fn不受绑定
,如果我运行. my-script.sh,则rm使用我的别名。

答案1

在获取脚本时,您始终可以禁用别名扩展:

shopt -u expand_aliases; . ./myscript.bash; shopt -s expand_aliases

myscript.bash仍将继承您可能在 中设置的变量、函数、umasks、限制、陷阱、重定向、选项等~/.bashrc

答案2

据我所知,没有办法自动将外部 shell 执行环境中所做的更改应用到当前 shell 执行环境。

以下是如何在不更改my-script.sh脚本的情况下部分完成此操作的概念证明:

{ . <(bash <(cat my-script.sh - <<'EOT'
declare -pf >&3
alias -p >&3
EOT
) 3>&1 1>&4); } 4>&1

这样, 的内容my-script.sh在其自己的非惰性实例中执行bash,该实例既不来源~/.bashrc也不继承别名以及非导出的变量和函数。declarealias与其连接以打印该环境中的别名和函数定义。文件描述符改组确保 的输出my-script.sh打印在外部标准输出(默认情况下,终端)上,而该source命令仅提供添加的alias和的输出declare
请注意(如斯蒂芬·查泽拉斯 指出)源内容将经历别名扩展,这可能会破坏本次练习的全部意义。
此外,命令行(例如在 的输出中ps)和子 Bash 进程中的命令名称(例如,在打印错误消息时使用)都没有什么意义——进程替换创建的临时文件的路径。

或者,您可以暂时保存当前环境的一部分,将其删除,获取脚本,然后恢复删除的部分。对于别名:

aliases=$(alias -p)
unalias -a
. my-script.sh
eval "$aliases"

对于函数:

shopt -s extglob                             # (There likely
functions=$(declare -pf)                     # is a cleaner
readarray -t funcnames < <(declare -pF)      # way to
unset -f "${funcnames[@]#declare -f*(x) }"   # do this)
. my-script.sh
eval "$functions"

再次需要注意的是, 的内容functions在使用时会进行别名扩展eval

相关内容