在源脚本中禁用 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 中实现,无法更改。 help
和 enable
列出所有 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 command
和 builtin
.
影响选择哪种类型
\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 -f
和 unalias
,并在最后恢复它们。但是,unset
对于只读函数可能会失败。更好的方法是在您不需要 source
的部分使用 bash -c '... functions and aliases have no effect here ...'
。对于其他部分,在所有内容前加上 command
.
请注意: 获取您脚本的调用者甚至可能禁用或隐藏 command
、builtin
等——因此您永远无法确保您实际使用的是您期望的命令。即使写 /usr/bin/env executable
或 /path/to/the/executable
也无济于事,因为函数可以有名称和 $PATH
或者文件系统可以改变。
但是,这不应该是您关心的问题。编写脚本的人应该负责提供正确的环境。
我知道我可以 运行 使用 \
或 ""
:
\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 中实现,无法更改。help
和enable
列出所有 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 command
和 builtin
.
\cmd
抑制别名
使用函数,built-ins,可执行文件command cmd
抑制别名和函数
使用 built-ins 和可执行文件builtin cmd
抑制别名、函数和可执行文件
仅使用 built-insenable -n cmd
完全禁用 built-incmd
,这样之后只有
使用别名、函数和可执行文件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 -f
和 unalias
,并在最后恢复它们。但是,unset
对于只读函数可能会失败。更好的方法是在您不需要 source
的部分使用 bash -c '... functions and aliases have no effect here ...'
。对于其他部分,在所有内容前加上 command
.
请注意: 获取您脚本的调用者甚至可能禁用或隐藏 command
、builtin
等——因此您永远无法确保您实际使用的是您期望的命令。即使写 /usr/bin/env executable
或 /path/to/the/executable
也无济于事,因为函数可以有名称和 $PATH
或者文件系统可以改变。
但是,这不应该是您关心的问题。编写脚本的人应该负责提供正确的环境。