Bagaimana cara memanggil shell built-in secara eksplisit?

13

Saya ingin menyesuaikan fungsionalitas cdperintah sesuai kebutuhan saya.

Saya mendefinisikan fungsi berikut - function cd () { cd "$@" && pushd "$@"; }

Tujuan dari fungsi ini adalah untuk secara otomatis mendorong direktori ke tumpukan sehingga menghemat upaya saya untuk mengetik secara manual pushd .setiap waktu.

Namun, fungsi di atas adalah fungsi rekursif tanpa batas, karena panggilan untuk cddiartikan sebagai fungsi itu sendiri dan bukan cdbuilt-in.

Bagaimana cara mereferensikan cdbuilt-in pada fungsi ini?

Saya tahu bahwa alias dapat dihindari dengan menggunakan \. Apa cara untuk menghindari fungsi atau referensi bawaan dengan cara yang lebih eksplisit?

Catatan: Saya tidak ingin mengubah nama fungsi saya menjadi hal lain.

Kshitiz Sharma
sumber
3
Kenapa tidak adil alias cd=pushd? Apa yang Anda harapkan terjadi ketika Anda melakukan sesuatu yang bukan jalur absolut (misalnya, cd ../)?
Patrick
@ Patrick pushdtidak mendukung -P. Tapi Anda benar, seperti yang ditunjukkan dalam pertanyaan itu function cdterlihat agak salah, karena mengubah direktori dua kali.
Tino

Jawaban:

5

The commandpasukan builtin nama perintah yang akan ditafsirkan sebagai builtin atau perintah eksternal (skipping alias dan fungsi lookup). Ini tersedia di semua shell POSIX termasuk bash.

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

(Perhatikan bahwa contoh ini buruk: contoh ini tidak berfungsi dengan jalur relatif, dan Anda mungkin cukup mengetikkan saja pushd.)

Di bash dan zsh (tetapi bukan ksh), Anda bisa menggunakan builtinuntuk memaksa nama perintah untuk ditafsirkan sebagai builtin, tidak termasuk alias, fungsi, dan perintah eksternal.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
16

Bash memiliki perintah (builtin) builtin, yang melakukan apa yang Anda butuhkan. Mengganti cddengan builtin cdfungsi Anda akan memperbaiki rekursi.

Petr Uzel
sumber
1

Saya curiga ketika Anda mengatakan Anda "tidak ingin mengubah nama fungsi Anda menjadi hal lain," Anda bermaksud bahwa Anda ingin dapat memanggil fungsi Anda dengan nama yang sama dengan perintah aslinya.

Jadi, cara lain untuk melakukan ini yang juga berfungsi untuk hal-hal yang tidak built-in, adalah memberi nama fungsi Anda sesuatu yang lain, dan kemudian mendefinisikan alias untuk perintah yang dibungkus. Ini berfungsi karena alias tidak ada dalam konteks eksekusi fungsi Anda.

Contoh wrapper.sh:

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

Dan di, misalnya, .bash_aliases:

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

Tapi ini cukup berantakan. Penggunaan commandlebih disukai bila memungkinkan.

matt2000
sumber
-1

Agar ini bekerja dengan jalur relatif, berikut ini akan diperlukan:

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

Ini mengasumsikan Anda berada pada distro Linux yang cukup modern yang berisi utilitas 'realpath'. (RHEL 6 tidak misalnya). Jika Perl tersedia, 'realpath' dapat disimulasikan menggunakan:

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