Jak jawnie wywołać wbudowaną powłokę?

14

Chcę dostosować funkcjonalność cdpolecenia zgodnie z moimi potrzebami.

Zdefiniowałem następującą funkcję - function cd () { cd "$@" && pushd "$@"; }

Celem tej funkcji jest automatyczne wypychanie katalogu na stos, dzięki czemu oszczędzam wysiłku, aby za pushd .każdym razem ręcznie pisać .

Jednak powyższa funkcja jest funkcją nieskończenie rekurencyjną, ponieważ wywołanie cdto interpretowane jest jako sama funkcja, a nie cdwbudowana.

Jak odwołać się do cdwbudowanej funkcji?

Wiem, że za pomocą aliasów można uciec \. W jaki sposób można uciec od funkcji lub odwoływać się do wbudowanych funkcji w bardziej wyraźny sposób?

Uwaga: nie chcę zmieniać nazwy mojej funkcji na nic innego.

Kshitiz Sharma
źródło
3
Dlaczego nie tylko alias cd=pushd? Czego oczekujesz, gdy wydarzy się cd do czegoś, co nie jest ścieżką absolutną (np. cd ../)?
Patrick
@Patrick pushdnie obsługuje -P. Ale masz rację, jak pokazano w pytaniu, function cdwygląda to nieco źle, ponieważ dwukrotnie zmienił katalog.
Tino

Odpowiedzi:

6

Te commandsiły wbudowane nazwę polecenia należy interpretować jako wbudowane lub zewnętrznego polecenia (z pominięciem alias i funkcja wyszukiwania). Jest dostępny we wszystkich powłokach POSIX, w tym bash.

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

(Zauważ, że ten przykład jest zły: nie działa ze ścieżkami względnymi i równie dobrze możesz po prostu wpisać pushdna pierwszym miejscu).

W bash i zsh (ale nie ksh) można użyć builtindo wymuszenia interpretacji nazwy polecenia jako wbudowanej, z wyłączeniem aliasów, funkcji i poleceń zewnętrznych.

Gilles „SO- przestań być zły”
źródło
16

Bash ma (wbudowane) polecenie builtin, które robi dokładnie to, czego potrzebujesz. Wymiana cdz builtin cdw funkcji ustali rekursji.

Petr Uzel
źródło
1

Podejrzewam, że kiedy mówisz, że „nie chcesz zmieniać nazwy swojej funkcji na nic innego”, masz na myśli, że chcesz móc wywoływać swoją funkcję o tej samej nazwie, co oryginalne polecenie.

Tak więc innym sposobem na zrobienie tego, co działa również w przypadku rzeczy, które nie są wbudowane, jest nadanie funkcji innej nazwy, a następnie zdefiniowanie aliasu dla zawiniętego polecenia. Działa to, ponieważ alias nie istnieje w kontekście wykonywania funkcji.

Przykład wrapper.sh:

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

I np. W .bash_aliases:

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

Ale to dość zuchwałe. Używanie commandjest zalecane, gdy jest to możliwe.

matt2000
źródło
-1

Aby to działało ze ścieżkami względnymi, potrzebne będą:

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

Zakłada się, że korzystasz z wystarczająco nowoczesnej dystrybucji Linuksa, która zawiera narzędzie „realpath”. (Na przykład RHEL 6). Jeśli dostępny jest Perl, „realpath” można symulować za pomocą:

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