如何覆盖 pushd 和 popd 对目录的自动调用?

Kev*_*ase 5 bash built-in bash-function

我的bash(4.1) 目录堆栈通常有十几个或更多条目。我想替换dirswith的输出dirs -v,所以我再也不用玩“猜幻数”pushd了。

我的部分解决方案

我替换dirsdirs -v使用执行的函数command

dirs()
{
    # "command" builtin prevents infinite recusion by suppressing lookup
    # of function and alias names.
    command dirs -v "${@}"
}
Run Code Online (Sandbox Code Playgroud)

(更新:根据气动学的建议,我现在使用builtin而不是command。它不能解决这个问题,但它稍微安全一些。)

dirs输出现在可读的,但pushdpopd仍产生旧呕吐-的-斜线

$ 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...
Run Code Online (Sandbox Code Playgroud)

dirs用别名替换我的函数后,我得到了相同(缺乏)的结果:

alias dirs='command dirs -v "${@}"'
Run Code Online (Sandbox Code Playgroud)

解决方法

我终于得到了我想要通过重写输出pushd以及popd还有:

pushd()
{
    command pushd "${@}" >/dev/null &&
      dirs
}
# popd is similar.
Run Code Online (Sandbox Code Playgroud)

这有效,但它需要覆盖三个内置函数而不是一个。此外,这可能是一个不完美的模仿pushdpopd在我还没有想过一些极端情况。我宁愿dirs只覆盖。

我的问题

为什么没有覆盖dirs工作? 根据bashman页面,在pushd和 下popd

如果pushd命令成功,adirs也会执行。

那么,为什么pushdpopd出现调用内置的dirs,而不是功能或别名吗?

关于bash文档的脚注

在线手册dirs中缺少说“a也执行”的段落,但它们出现在页面和. 我的4.1 文档和当前的 4.4 文档都以相同的方式不一致,这表明 4.4(如果我有的话)会表现相同。bashref.*manbash.*builtins.*bash

pne*_*ics 5

您想使用builtin而不是command. 我认为这就是您所追求的,覆盖到pushdand popd,同时保持dirs原样。

pushd(){ builtin pushd "$@" >/dev/null && dirs -v; }
popd() { builtin popd "$@" >/dev/null  && dirs -v; }
Run Code Online (Sandbox Code Playgroud)


bis*_*hop 4

根据我对bash 源代码的阅读,两者pushdpopd调用dirs内置函数本身(没有任何参数),而不是咨询定义的别名和函数。

虽然内置函数利用外部功能的情况似乎很少见,但当内置函数确实需要外部功能时,调用另一个内置函数似乎是先例。例如,当pushd更改目录时,它会调用cd内置的. 或者当declare需要对变量进行类型转换时,它会调用set内置的.

如何解决这个问题?pushd好吧,人们可以从源代码重新编译 bash:拥有并popd传递参数是微不足道的-v。人们还可以向上游请求 bash 添加一个环境变量,该变量定义了dirs用作pushd/的帮助程序时的默认选项popd。但似乎最快的用户空间解决方案就像您所做的那样:只需覆盖所有三个即可。