如何覆盖 pushd 和 popd 对 dirs 的自动调用?
How to override pushd's and popd's automatic call to dirs?
我的bash
(4.1) 目录堆栈通常有十几个或更多条目。我想用 dirs -v
替换 dirs
的输出,这样我就再也不用用 pushd
玩 "guess the magic number" 了。
我的部分解决方案
我将 dirs
替换为使用 command
:
执行 dirs -v
的函数
dirs()
{
# "command" builtin prevents infinite recusion by suppressing lookup
# of function and alias names.
command dirs -v "${@}"
}
(更新:在pneumatics' suggestion, I now use builtin
而不是command
。它没有解决这个问题,但它稍微安全一些。)
dirs
输出现在是可读的,但是 pushd
和 popd
仍然产生旧的斜线呕吐物:
$ pushd ~/just/one/more/and/ill/quit/i/promise
~/just/one/more/and/ill/quit/i/promise ~/tmp/bash/bash-4.1...
may/give/rise/to/dom /oh/no/not/again /var/adm/log /omg/wt...
va/lang ~/doc/comp/java/api/java/util/regex barf barf barf...
用别名替换我的 dirs
函数后,我得到了相同(缺少)的结果:
alias dirs='command dirs -v "${@}"'
解决方法
我最终通过覆盖 pushd
和 popd
得到了我想要的输出:
pushd()
{
command pushd "${@}" >/dev/null &&
dirs
}
# popd is similar.
这可行,但它需要覆盖 三个 内置函数而不是一个。此外,这可能是 pushd
和 popd
在某些我没有想到的极端情况下的不完美模仿。我宁愿只覆盖 dirs
。
我的问题
为什么覆盖 dirs
不起作用? 根据 bash
的 man
页面,pushd
和 popd
:
If the pushd
command is successful, a dirs
is performed as well.
那么为什么 pushd
和 popd
似乎调用内置函数 dirs
而不是函数或别名?
关于 bash
文档的脚注
"a dirs
is performed as well" 的段落在 bashref.*
online manual 中缺失,但出现在 man
页 bash.*
和 builtins.*
中。我的 bash
4.1 文档和当前的 4.4 文档以相同的方式不一致,这表明 4.4(如果我有的话)会表现相同。
您想使用 builtin
而不是 command
。我认为这就是您所追求的,覆盖 pushd
和 popd
,同时保持 dirs
不变。
pushd(){ builtin pushd "$@" >/dev/null && dirs -v; }
popd() { builtin popd "$@" >/dev/null && dirs -v; }
根据我对 bash source code, both pushd
and popd
call the dirs
内置函数(没有任何参数)的阅读,而不是咨询定义的别名和函数。
虽然内置函数很少利用外部功能,但当内置函数确实需要外部功能时,调用另一个内置函数似乎是先例。例如,当 pushd
更改目录时,it calls the cd
builtin. Or when declare
needs to type cast a variable, it calls the set
builtin.
如何解决这个问题?嗯,可以从源代码重新编译 bash:让 pushd
和 popd
传递 -v
参数是微不足道的。还可以向 bash 上游请求添加一个环境变量,该变量在用作 pushd
/popd
的助手时定义了默认的 dirs
选项。但似乎最快的用户空间解决方案就像您所做的那样:只需覆盖所有三个。
我的bash
(4.1) 目录堆栈通常有十几个或更多条目。我想用 dirs -v
替换 dirs
的输出,这样我就再也不用用 pushd
玩 "guess the magic number" 了。
我的部分解决方案
我将 dirs
替换为使用 command
:
dirs -v
的函数
dirs()
{
# "command" builtin prevents infinite recusion by suppressing lookup
# of function and alias names.
command dirs -v "${@}"
}
(更新:在pneumatics' suggestion, I now use builtin
而不是command
。它没有解决这个问题,但它稍微安全一些。)
dirs
输出现在是可读的,但是 pushd
和 popd
仍然产生旧的斜线呕吐物:
$ pushd ~/just/one/more/and/ill/quit/i/promise
~/just/one/more/and/ill/quit/i/promise ~/tmp/bash/bash-4.1...
may/give/rise/to/dom /oh/no/not/again /var/adm/log /omg/wt...
va/lang ~/doc/comp/java/api/java/util/regex barf barf barf...
用别名替换我的 dirs
函数后,我得到了相同(缺少)的结果:
alias dirs='command dirs -v "${@}"'
解决方法
我最终通过覆盖 pushd
和 popd
得到了我想要的输出:
pushd()
{
command pushd "${@}" >/dev/null &&
dirs
}
# popd is similar.
这可行,但它需要覆盖 三个 内置函数而不是一个。此外,这可能是 pushd
和 popd
在某些我没有想到的极端情况下的不完美模仿。我宁愿只覆盖 dirs
。
我的问题
为什么覆盖 dirs
不起作用? 根据 bash
的 man
页面,pushd
和 popd
:
If the
pushd
command is successful, adirs
is performed as well.
那么为什么 pushd
和 popd
似乎调用内置函数 dirs
而不是函数或别名?
关于 bash
文档的脚注
"a dirs
is performed as well" 的段落在 bashref.*
online manual 中缺失,但出现在 man
页 bash.*
和 builtins.*
中。我的 bash
4.1 文档和当前的 4.4 文档以相同的方式不一致,这表明 4.4(如果我有的话)会表现相同。
您想使用 builtin
而不是 command
。我认为这就是您所追求的,覆盖 pushd
和 popd
,同时保持 dirs
不变。
pushd(){ builtin pushd "$@" >/dev/null && dirs -v; }
popd() { builtin popd "$@" >/dev/null && dirs -v; }
根据我对 bash source code, both pushd
and popd
call the dirs
内置函数(没有任何参数)的阅读,而不是咨询定义的别名和函数。
虽然内置函数很少利用外部功能,但当内置函数确实需要外部功能时,调用另一个内置函数似乎是先例。例如,当 pushd
更改目录时,it calls the cd
builtin. Or when declare
needs to type cast a variable, it calls the set
builtin.
如何解决这个问题?嗯,可以从源代码重新编译 bash:让 pushd
和 popd
传递 -v
参数是微不足道的。还可以向 bash 上游请求添加一个环境变量,该变量在用作 pushd
/popd
的助手时定义了默认的 dirs
选项。但似乎最快的用户空间解决方案就像您所做的那样:只需覆盖所有三个。