¿Cómo invocar un shell incorporado explícitamente?

13

Quiero personalizar la funcionalidad del cdcomando según mis necesidades.

Definí la siguiente función: function cd () { cd "$@" && pushd "$@"; }

La intención de esta función es empujar automáticamente el directorio a la pila para que me ahorre el esfuerzo de escribir manualmente pushd .cada vez.

Sin embargo, la función anterior es una función infinitamente recursiva, ya que la llamada a cdse interpreta como la función misma y no como la cdincorporada.

¿Cómo hago referencia al cdincorporado en esta función?

Sé que los alias se pueden escapar usando \. ¿Cuál es la forma de escapar de las funciones o hacer referencia a las funciones incorporadas de una manera más explícita?

Nota: No quiero cambiar el nombre de mi función a otra cosa.

Kshitiz Sharma
fuente
3
¿Por qué no solo alias cd=pushd? ¿Qué esperas que suceda cuando cd a algo que no es un camino absoluto (por ejemplo, cd ../)?
Patrick
@Patrick pushdno es compatible -P. Pero tiene razón, como se muestra en la pregunta, se function cdve un poco mal, ya que cambió el directorio dos veces.
Tino

Respuestas:

5

El commandincorporado obliga a que un nombre de comando se interprete como un comando incorporado o externo (omitiendo alias y búsqueda de funciones). Está disponible en todos los shells POSIX, incluido bash.

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

(Tenga en cuenta que este ejemplo es malo: no funciona con rutas relativas, y también podría escribir pushden primer lugar).

En bash y zsh (pero no en ksh), puede usar builtinpara forzar que un nombre de comando se interprete como incorporado, excluyendo alias, funciones y comandos externos.

Gilles 'SO- deja de ser malvado'
fuente
16

Bash tiene un comando (incorporado) builtin, que hace exactamente lo que necesita. Reemplazar cdcon builtin cden su función arreglará la recursividad.

Petr Uzel
fuente
1

Sospecho que cuando dice que "no desea cambiar el nombre de su función a otra cosa", quiere decir que desea poder llamar a su función con el mismo nombre que el comando original.

Entonces, otra forma de hacer esto que también funciona para cosas que no están integradas, es nombrar a su función de otra manera y luego definir un alias para el comando envuelto. Esto funciona porque el alias no existe en el contexto de ejecución de su función.

Ejemplo wrapper.sh:

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

Y en, por ejemplo, .bash_aliases:

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

Pero esto es bastante hacky. Usar commandes preferible cuando sea posible.

matt2000
fuente
-1

Para que esto funcione con rutas relativas, se necesitaría lo siguiente:

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

Esto supone que está en una distribución Linux lo suficientemente moderna que contiene la utilidad 'realpath'. (RHEL 6 no, por ejemplo). Si Perl está disponible, 'realpath' se puede simular usando:

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