Wie rufe ich eine eingebaute Shell explizit auf?

13

Ich möchte die Funktionalität des cdBefehls gemäß meinen Anforderungen anpassen .

Ich habe die folgende Funktion definiert - function cd () { cd "$@" && pushd "$@"; }

Mit dieser Funktion soll das Verzeichnis automatisch auf den Stapel verschoben werden, damit ich nicht pushd .jedes Mal manuell tippen muss.

Die obige Funktion ist jedoch eine unendlich rekursive Funktion, da der Aufruf cdvon als die Funktion selbst und nicht als die cdeingebaute interpretiert wird .

Wie beziehe ich mich auf die cdin dieser Funktion eingebaute?

Ich weiß, dass Aliase mit entkommen werden können \. Wie können Funktionen oder Referenz-Built-Ins expliziter umgangen werden?

Hinweis: Ich möchte meine Funktion nicht in eine andere Funktion umbenennen.

Kshitiz Sharma
quelle
3
Warum nicht einfach alias cd=pushd? Was erwarten Sie, wenn Sie zu etwas wechseln, das kein absoluter Pfad ist (z. B. cd ../)?
Patrick
@Patrick pushdunterstützt nicht -P. Aber du hast recht, wie in der Frage gezeigt function cdsieht das ein bisschen falsch aus, da es das Verzeichnis zweimal gewechselt hat.
Tino

Antworten:

5

Das commandBuiltin erzwingt, dass ein Befehlsname als integrierter oder externer Befehl interpretiert wird (Alias ​​und Funktionssuche überspringen). Es ist in allen POSIX-Shells einschließlich Bash verfügbar.

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

(Beachten Sie, dass dieses Beispiel schlecht ist: Es funktioniert nicht mit relativen Pfaden, und Sie können es auch einfach pushdals erstes eingeben.)

In bash und zsh (aber nicht in ksh) können Sie builtinerzwingen, dass ein Befehlsname als eingebauter Name interpretiert wird, ausgenommen Aliase, Funktionen und externe Befehle.

Gilles 'SO - hör auf böse zu sein'
quelle
16

Bash hat einen (eingebauten) Befehl builtin, der genau das tut, was Sie brauchen. Durch Ersetzen cddurch builtin cdin Ihrer Funktion wird die Rekursion behoben.

Petr Uzel
quelle
1

Ich vermute, wenn Sie sagen, Sie möchten Ihre Funktion nicht in etwas anderes umbenennen, meinen Sie, Sie möchten Ihre Funktion mit dem gleichen Namen wie der ursprüngliche Befehl aufrufen können.

Eine andere Möglichkeit, dies auch für Dinge zu tun, die nicht integriert sind, besteht darin, Ihrer Funktion einen anderen Namen zu geben und dann einen Alias ​​für den umschlossenen Befehl zu definieren. Dies funktioniert, weil der Alias ​​im Ausführungskontext Ihrer Funktion nicht vorhanden ist.

Beispiel wrapper.sh:

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

Und in zB .bash_aliases:

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

Aber das ist ziemlich abgedreht. commandWenn möglich, ist die Verwendung vorzuziehen.

matt2000
quelle
-1

Damit dies mit relativen Pfaden funktioniert, ist Folgendes erforderlich:

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

Dies setzt voraus, dass Sie auf einer modernen Linux-Distribution sind, die das Dienstprogramm 'realpath' enthält. (RHEL 6 zum Beispiel nicht). Wenn Perl verfügbar ist, kann 'realpath' simuliert werden mit:

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