Как отменить автоматический вызов pushd и popd для dirs?

Мой 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 "${@}"
}

(Обновление: по предложению пневматики, я сейчас использую 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 "s man страница под обоими pushd а также popd:

Если pushd команда успешна, dirs также выполняется.

Так почему же pushd а также popd кажется, чтобы вызвать встроенный dirs вместо функции или псевдонима?

Сноска о bash Документация

Абзацы, говорящие "а dirs выполняется также "отсутствуют в bashref.* онлайн руководство, но они появляются в man страницы bash.* а также builtins.*, Оба мои bash Документы 4.1 и текущие документы 4.4 противоречивы в одном и том же порядке, что говорит о том, что 4.4 (если бы он у меня был) вел себя одинаково.

2 ответа

Решение

Из моего прочтения исходного кода bash оба pushd а также popd позвонить dirs встроенный сам (без каких-либо аргументов), вместо обращения к определенным псевдонимам и функциям.

Хотя кажется, что встроенная функция использует внешнюю функциональность редко, когда встроенная функция нуждается во внешней функции, вызов другой встроенной функции кажется прецедентом. Например, когда pushd меняет каталог, вызывает cd встроенный Или когда declare нужно набрать приведение переменной, он вызывает set встроенный

Как обойти это? Ну, можно перекомпилировать bash из исходного кода: было бы тривиально pushd а также popd пройти -v аргумент. Можно также попросить bash upstream добавить переменную окружения, которая определяет значение по умолчанию dirs варианты при использовании в качестве помощника pushd / popd, Но кажется, что самое быстрое решение для пользователей - то, что вы сделали: просто переопределите все три.

Вы хотите использовать builtin вместо command, Я думаю, что это то, что вы после, переопределяет pushd а также popd, оставляя dirs как есть.

pushd(){ builtin pushd "$@" >/dev/null && dirs -v; }
popd() { builtin popd "$@" >/dev/null  && dirs -v; }
Другие вопросы по тегам