Como invocar um shell embutido explicitamente?

13

Eu quero personalizar a funcionalidade de cd comando conforme minhas necessidades.

Eu defini a seguinte função - function cd () { cd "$@" && pushd "$@"; }

O objetivo desta função é enviar automaticamente o diretório para a pilha, para que me poupe o esforço de digitar manualmente pushd . todas as vezes.

No entanto, a função acima é uma função infinitamente recursiva, pois a chamada para cdé interpretada como sendo a própria função e não acd incorporada.

Como faço para referenciar o cd built-in nesta função?

Eu sei que aliases podem ser escapados usando \. Qual é a maneira de escapar de funções ou fazer referência a built-ins de maneira mais explícita?

Nota: Não quero renomear minha função para mais nada.

Kshitiz Sharma
fonte
3
Por que não apenas alias cd=pushd? O que você espera que aconteça quando você acessa algo que não é um caminho absoluto (por exemplo, cd ../)?
Patrick
@Patrick pushdnão suporta -P. Mas você está certo, como mostra a pergunta, function cdparece um pouco errado, pois mudou de diretório duas vezes.
Tino

Respostas:

5

O commandbuiltin força um nome de comando a ser interpretado como um comando interno ou externo (ignorando alias e pesquisa de função). Está disponível em todos os shells POSIX, incluindo o bash.

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

(Observe que este exemplo é ruim: ele não funciona com caminhos relativos e você pode apenas digitar pushdem primeiro lugar.)

No bash e no zsh (mas não no ksh), você pode builtinforçar um nome de comando a ser interpretado como interno, excluindo aliases, funções e comandos externos.

Gilles 'SO- parar de ser mau'
fonte
16

O Bash possui um comando (interno) builtin, que faz exatamente o que você precisa. Substituir cdpor builtin cdna sua função corrigirá a recursão.

Petr Uzel
fonte
1

Eu suspeito que quando você diz que "não deseja renomear sua função para outra coisa", quer dizer que deseja chamar sua função pelo mesmo nome que o comando original.

Portanto, outra maneira de fazer isso que também funciona para coisas que não são integradas é nomear sua função de outra maneira e definir um alias para o comando agrupado. Isso funciona porque o alias não existe no contexto de execução da sua função.

Exemplo wrapper.sh:

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

E em, por exemplo, .bash_aliases:

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

Mas isso é bastante hacky. commandÉ preferível usar quando possível.

matt2000
fonte
-1

Para que isso funcione com caminhos relativos, seria necessário o seguinte:

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

Isso pressupõe que você esteja em uma distribuição Linux moderna o suficiente que contenha o utilitário 'realpath'. (RHEL 6 não, por exemplo). Se o Perl estiver disponível, 'realpath' pode ser simulado usando:

! realpath $(pwd) > /dev/null 2>&1  && function realpath {
    perl -e "use Cwd realpath; print realpath(\"$1\") . \"\\n\";"
}
Vinny
fonte