在源脚本中禁用 functions/aliases

Disable functions/aliases in a sourced script

我知道我可以 运行 使用 \"":

的“原始”命令(不是别名)
\ls
"ls"

但这不适用于函数。此外,它要求我每次都使用该语法。

是否可以在源脚本中禁用父进程中的所有 functions/aliases(运行 是我的脚本)? IE。如果用户在他们的终端中定义了一些别名函数,我希望在我的脚本中禁用它们(但当然我仍然希望能够定义和使用我自己的 aliases/functions)。

编辑:这个答案可能不再相关,因为您编辑了问题以澄清脚本是源代码,而不是在子shell.

中执行

这是默认情况下发生的。证明:

$ function x() { echo 'hi'; }
$ x
hi
$ bash
# We are now in a subshell.
$ x
bash: x: command not found

函数通常在 shell 的启动文件之一中定义:.bashrc.profile.bash_profile。其中哪些来源取决于 shell 是 login shell and/or 还是 interactive shell。调用以执行 shell 脚本的 shell 既不是登录 shell 也不是交互式 shell,在这种情况下,这些文件的 none 是来源的。

编辑:我应该更仔细地阅读,因为你不想获取脚本,而是获取来源,以下是相反的方式:

函数

如果您在开始时获取您的父脚本,您可以循环遍历定义的函数并取消设置它们。

declare -F 将列出所有已定义的函数,但格式为 declare -f functioname,因此您只需获取名称:

IFS=$'\n'
for f in $(declare -F|cut -d ' ' -f 3); do
    unset -f $f
done

别名

别名不应该像我记得的那样来源,但如果他们在那里你可以做

unalias -a

全部取消设置。

Bash

中的命令类型

Bash 知道可以相互影响的不同类型的命令。这些类型的优先级是:

  • 别名
    可以由用户使用alias cmd=...
  • 定义
  • 函数
    可以由用户使用cmd() { ... }
  • 定义
  • built-ins
    直接在 bash 中实现,无法更改。 helpenable 列出所有 built-ins.
  • $PATH
  • 中的可执行文件

意思是如果你输入cmd arg1 arg2 ...你使用别名cmd如果它被定义,否则你使用函数cmd如果它被定义,否则你使用built-in cmd 如果它是 built-in,否则你使用 $PATH 目录中的第一个可执行文件 cmd 如果有的话,否则你会得到错误 -bash: cmd command not found.

可以使用 type -a cmd 检查哪些情况适用于 cmd

手动优先控制

Bash 允许您使用引号和 built-ins commandbuiltin.

影响选择哪种类型
  • \cmd
    抑制别名
    使用函数,built-ins,可执行文件
  • command cmd
    抑制别名和函数
    使用 built-ins 和可执行文件
  • builtin cmd
    抑制别名、函数和可执行文件
    仅使用 built-ins
  • enable -n cmd
    完全禁用 built-in cmd,这样之后只有
    使用别名、函数和可执行文件
  • env cmd
    不是 bash built-in,因此它并没有真正抑制任何东西,但
    仅使用可执行文件

例子

阴影完全正常。例如,bash 有自己的 built-in echo,但您的系统也有 /bin/echo。两种实现可能不同。例如,我的 bash 5 中的 echo 支持 \uXXXX 但我的 GNU coreutils 8.3 中的 echo 不支持。如果您使用别名和函数添加自己的实现,则这种差异的可能性会变得更加明显。这是交互式 bash 会话中的示例($ 是提示):

$ echo() { printf "function echo: %s\n" "$*"; }
$ alias echo='printf "alias echo: %s %s %s\n"'
$ type -a echo
echo is aliased to `printf "alias echo: %s %s %s\n"'
echo is a function
echo ()
{
    printf "function echo: %s\n" "$*"
}
echo is a shell builtin
echo is /bin/echo

$ echo -e '\u2261'
alias echo: -e \u2261
$ \echo -e '\u2261'
function echo: -e \u2261
# use the built-in (or executable file if there was no such built-in)
$ command echo -e '\u2261'
≡
$ builtin echo -e '\u2261'
≡

# use the executable /bin/echo
$ env echo -e '\u2261'
\u2261

$ enable -n echo
# use the executable /bin/echo (`command` is needed to skip the alias and function)
$ command echo -e '\u2261'
\u2261

回答您的问题

不幸的是,我不知道 enable 之类的东西可以永久禁用别名和函数查找。您可以尝试一些技巧,例如备份所有别名和函数,对它们执行 unset -funalias,并在最后恢复它们。但是,unset 对于只读函数可能会失败。更好的方法是在您不需要 source 的部分使用 bash -c '... functions and aliases have no effect here ...'。对于其他部分,在所有内容前加上 command.

请注意: 获取您脚本的调用者甚至可能禁用或隐藏 commandbuiltin 等——因此您永远无法确保您实际使用的是您期望的命令。即使写 /usr/bin/env executable/path/to/the/executable 也无济于事,因为函数可以有名称和 $PATH 或者文件系统可以改变。 但是,这不应该是您关心的问题。编写脚本的人应该负责提供正确的环境。