2015-12-21 46 views
13

Jaki jest najlepszy sposób zdefiniowania aliasu, jeśli, powiedzmy, plik wykonywalny "ag" zostanie znaleziony?Najlepszy sposób definiowania aliasów "warunkowych" w powłoce

if (($+commands[ag])) ; then alias grep='ag'; fi 

lub

[[ -s $(which ag) ]] && alias grep='ag' 

lub

if $(which ag >& /dev/null); then alias grep='ag'; fi 

czy ...?

Według najlepszej, mam na myśli bardziej solidny, bardziej wydajny i/lub bardziej przenośny (Bash, Zsh).

Jaka jest twoja rada?

Odpowiedz

9

Nie widzę, jak prosty oczywisty wariant POSIX miałby jakąkolwiek wadę w porównaniu z alternatywnymi (w większości nieprzenośnymi), które proponujecie.

type ag >/dev/null 2>&1 && alias grep=ag 
+0

Ładne i czyste. Zasadniczo odpowiadając na moje pytanie. – user3341592

+0

Pytanie boczne: lepiej używać '' 'type ag> &/dev/null''' lub po prostu' '' type ag>/dev/null''' (tak jak ty)? – user3341592

+1

Ten pierwszy nie jest przenośny. Jeśli chcesz przekierować stderr, to '2>/dev/null' lub'>/dev/null 2> & 1' dla stdout i stderr. – tripleee

1

Używam tego pathto funkcję przenoszenia wszystkich dziedzictwa powłoki Bourne'a (nie używam which, ponieważ nie jest w POSIX więc jego format jest nieokreślona i narzeka, gdy nic nie zostanie znaleziony, zamiast być cichy):

pathto() { 
     DIRLIST=`echo $PATH|tr : ' '` 
     for e in "[email protected]"; do 
       for d in $DIRLIST; do 
         test -f "$d/$e" -a -x "$d/$e" && echo "$d/$e" 
       done 
     done 
} 

który Echos ścieżkę do dowolnego pliku wykonywalnego danego gdy stwierdzono, wraz z

test "`pathto less`" != "" && alias more=less 

jeśli chodzi o wydajność, nie należy dbać, ponieważ kilka razy zadzwonić pathto jest znikoma. Twoje pierwsze dwa przykłady używają nieprzenośnych konstrukcji (()) i [[ ]] i należy ich unikać.

Należy również zauważyć, że nie zajmowałem się konkretnie pustymi częściami w PATH. Ze względów bezpieczeństwa należy ich unikać, tak jak ..

+2

Jest to niewiarygodne, jeśli jakiekolwiek wpisy w '$ PATH' zawierają spacje. Ale ustalenie, że w mniej-macierzowych (i '<(...)' -dowolnych) powłokach Bourne'a będzie wymagało trochę pracy (chociaż utrzymanie 'echo' jako wyjścia oznacza, że ​​możesz użyć tego z normalną rurą i przyjmując' printf', który może wyjście "\ 0" można to zrobić ... myślę). Również to * robi *, w pewnym sensie, radzi sobie z pustymi wartościami '$ PATH', ponieważ ignoruje je całkowicie, gdy zostaną zrzucone w pętli' for d in $ DIRLIST'. Powiedział, że robi to w sposób, który oznacza, że ​​przegapi fakt, że sama powłoka zobaczy polecenie w bieżącym katalogu. –

+1

Wykorzystuje to również wycofany argument '-a' do' testowania 'i nie może być użyty z więcej niż jednym poleceniem, jeśli sama nazwa polecenia zawiera spację (ignorując problem '$ PATH' ze spacjami). (I tak, poważnie wątpię, że to jest problem, który kiedykolwiek się pojawi, ale pomyślałem, że i tak warto o tym wspomnieć.) –

+0

@EtanReisner Twoja pedanteria jest doceniana, dzięki! :-) Wesołych Świąt. – Jens