Niech bash używa zewnętrznego polecenia `time` zamiast wbudowanej powłoki

27

Jak ustawić domyślnie bash czas binarny (/ usr / bin / time) zamiast słowa kluczowego powłoki?

which timezwraca /usr/bin/time
type timezwraca time is a shell keyword
Uruchomienie timeoczywiście wykonuje słowo kluczowe powłoki:

$ 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 zwraca bash: enable: time: not a shell builtin

David Holdeman
źródło

Odpowiedzi:

30

Możesz użyć commandwbudowanej powłoki, aby ominąć normalny proces wyszukiwania i uruchomić dane polecenie jako polecenie zewnętrzne, niezależnie od innych możliwości (wbudowane powłoki, aliasy itp.). Często odbywa się to za pomocą skryptów, które muszą być przenośne w różnych systemach, chociaż prawdopodobnie częściej używa się stenografii \(jak w lub \rmzamiast , ponieważ szczególnie ta ostatnia może być aliasowana do czegoś nie znanego ).command rmrmrm -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...]
$ 

Można tego użyć z aliasem, takim jak:

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

Zaletą tego jest na przykład alias time=/usr/bin/timeto, że nie określasz pełnej ścieżki do timepliku binarnego, ale zamiast tego powracasz do zwykłego mechanizmu wyszukiwania ścieżki.

Sama aliaskomenda może przejść do np. ~ / .Bashrc lub /etc/bash.bashrc (ta ostatnia jest globalna dla wszystkich użytkowników w systemie).

W przeciwnym przypadku (wymuszenie użycia wbudowanej powłoki w przypadku zdefiniowania aliasu) użyłbyś czegoś podobnego builtin time, co ponownie zastąpi zwykły proces wyszukiwania i uruchomi nazwaną wbudowaną powłokę. Strona podręcznika bash wspomina, że ​​jest to często używane w celu zapewnienia niestandardowej cdfunkcjonalności o nazwie o nazwie cd, która z kolei używa wbudowanej funkcji cddo wykonania prawdziwej operacji.

CVn
źródło
Możesz również dowiedzieć się, skąd pochodzi określone polecenie, używając polecenia type -a <cmd>.
slm
12
commandnie omija wbudowanych (z wyjątkiem zshgdy nie emuluje innych powłok). Pomija funkcje i to jest główny powód jego istnienia. Jej druga rola jest usunięcie specjalnego w szczególnych poleceń wbudowanych . Pomija aliasy i słowa kluczowe tylko dlatego, że są one rozwijane tylko na pierwszej pozycji ( zshna przykład nie pomija globalnych aliasów). Nie ma timewbudowanego basha. timejest słowem kluczowym, na przykład możesz to zrobić time { foo; bar; }.
Stéphane Chazelas,
1
@StephaneChazelas W każdym razie możesz edytować to w odpowiedzi, aby podać dokładniejszy opis. commanddziała w tym konkretnym przypadku, jak na przykładzie, ale oczywiście poprawna odpowiedź jest lepsza niż odpowiedź w połowie prawidłowa.
CVn
1
Ostatnia część twojej odpowiedzi jest nieprawidłowa. czas nie jest wbudowaną powłoką, lecz słowem kluczowym powłoki. builtin timenie działa
Teresa e Junior
podobne do polecenia byłoby po prostu zacytować:'time' echo test
mxmlnkn
9

W bash istnieje skrót do omijania słów kluczowych, bez konieczności określania ścieżki lub korzystania z innego wbudowanego narzędzia, takiego jak command: Escape from 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...]

Osobiście uważam to za bardziej czytelne i bezpieczniejsze, ponieważ jest to możliwe:

=^_^= izkata@Izein:~$ alias command=echo
=^_^= izkata@Izein:~$ command time
time
Izkata
źródło
8
Należy pamiętać, że każda forma cytowania lub czegokolwiek, co sprawia, że nie token timezrobi: ti\me, 'time', ti""me, ti${-##*}me, ${-+time}... Dotyczy to jakiekolwiek słowo kluczowe powłoki.
Stéphane Chazelas,
Najlepsze PS1, jakie widziałem.
maxywb
1
@maxywb Poza tym nie jest to tylko dekoracja - jeśli ostatnie polecenie nie powiedzie się, szczęśliwa twarz zmieni kolor na czerwony(x_x)
Izkata
4

Ogólne rozwiązania dla wbudowanych (na przykład test) są [1] :

  • use env(wszystkie muszle)

    $ env test
    external test
    
  • wyłącz wbudowane (tylko bash i 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
    
  • użyj dowolnego ukośnika, /aby wywołać polecenie (wszystkie powłoki):

    $ test 1 = 1 && echo "yes"
    yes 
    $ ~/bin/test
    external test
    
  • utwórz alias (kończy się niepowodzeniem w skrypcie bash, chyba że shopt -s expand_aliasesjest używany):

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

Ale czas nie jest wbudowany.

Słowo timeto jest „słowem zastrzeżonym”, a nie poleceniem ani wbudowanym. Dzięki temu możliwe są następujące rozwiązania:

  • Cytuj słowo. To nie działa z wbudowanymi.
    Wiele form cytowania pracy: \time "time" 'time' ti\me ti"me"itp.

    $  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...]
    

    Jest to przydatne do ominięcia aliasu. Nawet jeśli testjest aliasowany, \testwykona polecenie PATHed (lub wbudowane, jeśli nie zostało wyłączone).

  • Użyj wbudowanego command(nie działa z wbudowanymi):

    $ command time
  • Jak wyżej dla wbudowanych, używając dowolnego slash /działa:

    $ /usr/bin/time
  • Jak wyżej dla wbudowanych, tutaj działa także alias:

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

[1] Załóżmy, że istnieje zewnętrzny plik wykonywalny, ~/bin/testktóry drukuje „test zewnętrzny”. I dalej: załóżmy, że ~/binwyprzedza /binaktywna ŚCIEŻKA.


źródło
2

Upuść to w ~/.bashrc:

alias time=/usr/bin/time

TravisThomas
źródło
2

Możesz użyć tego enablepolecenia, aby wyłączyć niektóre wbudowane funkcje .

$ enable -n kill

Jednak timejest to słowo kluczowe, tak to nie będzie działać.

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

Pozostaje Ci zatem utworzenie aliasu, aby go zastąpić:

$ alias time=/usr/bin/time
slm
źródło
nie. czas jest słowem kluczowym powłoki, a nie wbudowaną powłoką. Właśnie miałem edytować moje pytanie, aby powiedzieć, że enable -n nie działa, gdy zobaczyłem, że odpowiedziałeś.
David Holdeman,