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

我的部分解决方案

我将dirs替换为使用 dirs -v 执行command的函数:

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

(更新:在pneumatics' suggestion,我现在使用 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...

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

alias dirs='command dirs -v "${@}"'

解决方法

我最终也通过覆盖pushdpopd获得了想要的输出:

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

这可行,但是它需要覆盖三个内建而不是一个。另外,在我未曾想到的某些极端情况下,这可能是对pushdpopd的不完美模仿。我宁愿只覆盖dirs

我的问题

为什么不覆盖dirs起作用? 根据bashman页面,在pushdpopd下:



那么,为什么pushdpopd似乎调用了内置的dirs而不是函数或别名?

关于bash文档的脚注

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

最佳答案

根据我对bash source code的阅读, pushd popd 都调用 dirs 内置自身(没有任何参数),而不是引用已定义的别名和函数。

尽管内建函数很少利用外部功能,但是当内建函数确实需要外部功能时,调用另一个内建函数似乎是先例。例如,当pushd更改目录it calls the cd builtin时。或者,当declare需要输入类型时,将其转换为it calls the set builtin

如何解决这个问题?好吧,可以从源代码重新编译bash:让pushdpopd传递-v参数是微不足道的。还可以在上游请求bash来添加一个环境变量,该环境变量在用作dirs/pushd的助手时定义了默认的popd选项。但这似乎是最快的userland解决方案,就像您已经完成的一样:只需覆盖所有这三个即可。

关于bash - 如何覆盖插入和弹出的对dirs的自动调用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39715474/

10-12 17:10