Buat bash menggunakan perintah `time` eksternal alih-alih shell built-in

27

Bagaimana saya bisa membuat bash menggunakan binary waktu (/ usr / bin / time) secara default, bukan kata kunci shell?

which timepengembalian /usr/bin/time
type timepengembalian time is a shell keyword
Menjalankan timejelas mengeksekusi kata kunci shell:

$ time

real    0m0.000s
user    0m0.000s
sys     0m0.000s
$ /usr/bin/time
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]
   [--portability] [--format=format] [--output=file] [--version]
   [--quiet] [--help] command [arg...]

enable -n time kembali bash: enable: time: not a shell builtin

David Holdeman
sumber

Jawaban:

30

Anda dapat menggunakan commandshell built-in untuk mem-bypass proses pencarian normal dan menjalankan perintah yang diberikan sebagai perintah eksternal terlepas dari segala kemungkinan lain (shell built-in, alias, dll.). Hal ini sering dilakukan dalam skrip yang harus portabel di seluruh sistem, meskipun mungkin lebih sering menggunakan singkatan \(seperti dalam \rmdaripada command rmatau rm, karena terutama yang terakhir mungkin alias sesuatu yang tidak diketahui seperti rm -i).

$ time

real    0m0.000s
user    0m0.000s
sys 0m0.000s
$ command time
Usage: time [-apvV] [-f format] [-o file] [--append] [--verbose]
       [--portability] [--format=format] [--output=file] [--version]
       [--quiet] [--help] command [arg...]
$ 

Ini dapat digunakan dengan alias, seperti:

$ alias time='command time'
$ time
Usage: time [-apvV] [-f format] [-o file] [--append] [--verbose]
       [--portability] [--format=format] [--output=file] [--version]
       [--quiet] [--help] command [arg...]
$ 

Keuntungan dari contoh alias time=/usr/bin/timeini adalah bahwa Anda tidak menentukan path lengkap ke timebiner, tetapi sebaliknya kembali ke mekanisme pencarian path yang biasa.

The aliasperintah itu sendiri dapat masuk ke misalnya ~ / .bashrc atau /etc/bash.bashrc (yang terakhir ini global untuk semua pengguna di sistem).

Untuk kasus sebaliknya (memaksa penggunaan shell built-in jika ada alias yang ditentukan), Anda akan menggunakan sesuatu seperti builtin time, yang lagi-lagi mengesampingkan proses pencarian yang biasa dan menjalankan shell built-in yang bernama. Halaman bash man menyebutkan bahwa ini sering digunakan untuk menyediakan cdfungsionalitas khusus dengan fungsi bernama cd, yang pada gilirannya menggunakan builtin cduntuk melakukan hal yang sebenarnya.

sebuah CVn
sumber
Anda juga dapat menanyakan dari mana perintah tertentu berasal dari menggunakan perintah tersebut type -a <cmd>.
slm
12
commandtidak mem-bypass builtin (kecuali zshketika tidak meniru shell lain). Ini melewati fungsi dan itulah alasan utama keberadaannya. Peran keduanya adalah untuk menghapus spesial dalam builtin khusus . Itu mem-bypass alias dan kata kunci hanya karena itu hanya diperluas di posisi pertama ( zshmisalnya, ia tidak mem-bypass alias global). Tidak ada timebash bawaan. timeadalah kata kunci sehingga Anda dapat melakukannya misalnya time { foo; bar; }.
Stéphane Chazelas
1
@StephaneChazelas Jangan ragu untuk mengeditnya menjadi jawaban untuk memberikan deskripsi yang lebih akurat. commandbekerja dalam kasus khusus ini, seperti yang dicontohkan, tetapi jelas jawaban yang benar lebih baik daripada yang setengah benar.
CVn
1
Bagian terakhir dari jawaban Anda salah. waktu bukanlah shell builtin, melainkan kata kunci shell. builtin timetidak bekerja
Teresa e Junior
mirip dengan perintah akan hanya mengutipnya:'time' echo test
mxmlnkn
9

Ada pintasan di bash untuk menghindari kata kunci, tanpa harus menentukan jalur atau menggunakan bawaan lain seperti command: Melarikannya dengan backslash.

=^_^= izkata@Izein:~$ time

real    0m0.000s
user    0m0.000s
sys     0m0.000s
=^_^= izkata@Izein:~$ \time
Usage: time [-apvV] [-f format] [-o file] [--append] [--verbose]
       [--portability] [--format=format] [--output=file] [--version]
       [--quiet] [--help] command [arg...]

Secara pribadi, saya menemukan ini lebih mudah dibaca dan lebih aman, karena ini mungkin:

=^_^= izkata@Izein:~$ alias command=echo
=^_^= izkata@Izein:~$ command time
time
Izkata
sumber
8
Perhatikan bahwa setiap bentuk mengutip atau apapun yang membuatnya tidak token timeakan melakukan: ti\me, 'time', ti""me, ti${-##*}me, ${-+time}... Itu berlaku untuk setiap shell kata kunci.
Stéphane Chazelas
PS1 Terbaik yang pernah saya lihat.
maxywb
1
@maxywb Juga, ini bukan hanya dekoratif - jika perintah terakhir gagal, wajah bahagia berubah menjadi merah(x_x)
Izkata
4

Solusi umum untuk built-in (misalnya tes) adalah [1] :

  • gunakan env(semua kerang)

    $ env test
    external test
    
  • nonaktifkan builtin (hanya bash dan zsh):

    $ test 1 = 1 && echo "yes"
    yes
    $ enable -n test        ### for bash. Re-enable with "enable test".
    $ disable test          ### for zsh. Re-enable with "enable test".
    $ test
    external test
    
  • gunakan sembarang slash /untuk memanggil perintah (semua shell):

    $ test 1 = 1 && echo "yes"
    yes 
    $ ~/bin/test
    external test
    
  • membuat alias (gagal di dalam skrip bash, kecuali jika shopt -s expand_aliasesdigunakan):

    $ alias test='~/bin/test'             ### remove with 'unalias test'.
    $ test
    external test
    

Tetapi waktu bukanlah suatu bawaan.

Kata itu timeadalah "kata yang dicadangkan", bukan perintah dan bukan built-in. Itu memungkinkan solusi ini:

  • Kutip kata itu. Ini tidak berfungsi dengan built-in.
    Banyak bentuk pekerjaan mengutip:, \time "time" 'time' ti\me ti"me"dll.

    $  time
    
    real    0m0.000s
    user    0m0.000s
    sys     0m0.000s
    
    $ \time
    Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]
           [--portability] [--format=format] [--output=file] [--version]
           [--quiet] [--help] command [arg...]
    

    Ini berguna untuk memotong alias. Bahkan jika testalias, \testakan menjalankan perintah PATHed (atau builtin jika belum dinonaktifkan).

  • Gunakan builtin command(ini tidak berfungsi dengan built-in):

    $ command time
  • Seperti di atas untuk built-in, menggunakan slash /works:

    $ /usr/bin/time
  • Seperti di atas untuk bawaan, alias juga berfungsi di sini:

    $ alias time='command time'
    $ alias time='/usr/bin/time'
    

[1] Mari kita asumsikan ada executable eksternal ~/bin/testyang mencetak "tes eksternal". Dan selanjutnya: mari kita asumsikan bahwa ~/binada di depan /bindalam PATH aktif.


sumber
2

Masukkan ini ke ~/.bashrc:

alias time=/usr/bin/time

TravisThomas
sumber
2

Anda dapat menggunakan enableperintah untuk menonaktifkan built-in tertentu.

$ enable -n kill

Namun timeadalah kata kunci sehingga ini tidak akan berfungsi.

$ builtin time
bash: builtin: time: not a shell builtin

Jadi Anda harus membuat alias untuk menimpanya:

$ alias time=/usr/bin/time
slm
sumber
nggak. waktu adalah kata kunci shell, bukan shell builtin. Saya baru saja akan mengedit pertanyaan saya untuk mengatakan bahwa mengaktifkan -n tidak berfungsi ketika saya melihat Anda telah menjawab.
David Holdeman