禁用源脚本中的功能/别名 Bash中的命令类型手动优先控制示例回答您的问题

问题描述

我知道我可以使用\""来运行“原始”命令(不是别名):

\ls
"ls"

但这不适用于功能。另外,它要求我每次都使用该语法。

是否可以在源脚本中禁用父进程(运行我的脚本的一个)的所有功能/别名?即如果终端中的用户定义了一些别名功能,我希望在脚本中将其禁用(但我当然仍然希望能够定义和使用自己的别名/功能)。

解决方法

Bash中的命令类型

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

  • 别名
    可以由用户使用alias cmd=...
  • 来定义
  • 功能
    可以由用户使用cmd() { ... }
  • 来定义
  • 内置插件
    是直接在bash中实现的,不能更改。 helpenable列出所有内置插件。
  • $PATH中的可执行文件

意思是如果您输入cmd arg1 arg2 ...,则使用别名cmd(如果已定义);否则,则使用函数cmd(如果已定义);否则,请使用内置的{{ 1}}(如果它是内置的),否则使用cmd中的目录中的第一个可执行文件cmd(如果存在的话),否则将出现错误$PATH。>

可以使用-bash: cmd command not found来检查其中哪些情况适用于cmd

手动优先控制

Bash允许您使用引号以及内置的type -a cmdcommand来影响选择哪种类型。

  • builtin
    禁止使用别名
    使用函数,内置函数,可执行文件
  • \cmd
    禁止使用别名和功能
    使用内置和可执行文件
  • command cmd
    禁止别名,函数和可执行文件
    仅使用内置
  • builtin cmd
    完全禁用内置enable -n cmd,以便仅在之后禁用
    使用别名,函数和可执行文件
  • cmd
    不是内置的bash,因此除了
    仅使用可执行文件

示例

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

$ 

回答您的问题

不幸的是,我不知道像$ 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 这样的东西来永久禁用别名和函数查找。您可以尝试一些技巧,例如备份所有别名和函数,对它们进行enableunset -f,最后进行还原。但是,unalias对于只读功能可能会失败。更好的方法是将unset用于您确实不需要bash -c '... functions and aliases have no effect here ...'好处的部分。对于其他部分,请在所有内容前加上source

请注意:发出脚本的调用者甚至可能禁用或隐藏commandcommand等,因此您永远无法确定自己是实际使用您期望的命令。即使编写builtin/usr/bin/env executable也无济于事,因为函数可以使用名称和/path/to/the/executable或可以更改文件系统。 但是,这不应该是您的问题。源于您脚本的人应该负责提供正确的环境。

,

编辑:此答案可能不再相关,因为您已编辑问题以阐明脚本是源程序,而不是在子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。这些源中的哪一个取决于外壳是 login 外壳和/还是 interactive 外壳。调用执行外壳脚本的外壳既不是登录外壳也不是交互式外壳,在这种情况下,这些文件都不是源文件。

,

编辑:我应该更仔细地阅读,因为您不想获取脚本,但是希望获取脚本,以下是相反的方法:

功能

如果您一开始就获取父脚本,则可以循环浏览已定义的函数并取消设置它们。

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

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

别名

我不记得应该使用别名,但是如果存在别名,您可以这样做

unalias -a

全部取消设置。