Как явно вызвать встроенную оболочку?


13

Я хочу настроить функциональность cdкоманды в соответствии с моими потребностями.

Я определил следующую функцию - function cd () { cd "$@" && pushd "$@"; }

Цель этой функции - автоматически поместить каталог в стек, чтобы сэкономить время, необходимое для ввода вручную pushd .каждый раз.

Однако указанная выше функция является бесконечно рекурсивной, так как вызов cdинтерпретируется как сама функция, а не как cdвстроенная.

Как мне ссылаться на cdвстроенную в эту функцию?

Я знаю, что псевдонимы можно избежать с помощью \. Каким образом можно избегать функций или ссылаться на встроенные модули более явным образом?

Примечание. Я не хочу переименовывать свою функцию во что-либо еще.


3
Почему не просто alias cd=pushd? Что вы ожидаете случиться, когда вы перейдете к чему-то, что не является абсолютным путем (например, cd ../)?
Патрик

@ Патрик pushdне поддерживает -P. Но вы правы, как показано в вопросе, function cdвыглядит немного неправильно, так как он дважды менял каталог.
Тино

Ответы:


5

В commandBUILTIN сила имя команды должна интерпретироваться как встроенная , так и внешняя команда (пропуск псевдонима и функция поиска). Он доступен во всех оболочках POSIX, включая bash.

cd () { command cd "$@" && pushd "$@"; }

(Обратите внимание, что этот пример плохой: он не работает с относительными путями, и вы могли бы просто напечатать pushdв первую очередь.)

В bash и zsh (но не в ksh) вы можете использовать, builtinчтобы имя команды интерпретировалось как встроенное, исключая псевдонимы, функции и внешние команды.


16

Bash имеет (встроенную) команду builtin, которая делает именно то, что вам нужно. Замена cdна builtin cdв вашей функции исправит рекурсию.


1

Я подозреваю, что когда вы говорите, что «не хотите переименовывать свою функцию во что-либо еще», вы подразумеваете, что хотите иметь возможность вызывать вашу функцию с тем же именем, что и исходная команда.

Итак, еще один способ сделать это, который также работает для вещей, которые не являются встроенными, это присвоить вашей функции другое имя, а затем определить псевдоним для перенесенной команды. Это работает, потому что псевдоним не существует в контексте выполнения вашей функции.

Пример wrapper.sh:

#!/bin/bash
function my_wrapper() { wrapped_program $@ && dostuff }

И, например, .bash_aliases:

source /path/to/wrapper.sh
alias wrapped_program="my_wrapper"

Но это довольно глупо. Использование commandпредпочтительнее, когда это возможно.


-1

Чтобы это работало с относительными путями, необходимо следующее:

function cd { 
   dir="$(realpath "$@")"
   command cd "$dir"
   pushd "$dir"
}

Это предполагает, что вы находитесь в достаточно современном дистрибутиве Linux, который содержит утилиту 'realpath'. (RHEL 6 не например). Если Perl доступен, 'realpath' может быть смоделирован с использованием:

! realpath $(pwd) > /dev/null 2>&1  && function realpath {
    perl -e "use Cwd realpath; print realpath(\"$1\") . \"\\n\";"
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.