W jaki sposób mogę uwzględnić w skryptach konfiguracyjnych powłoki różnice między coreutils na BSD w porównaniu z GNU?

9

Do tego miesiąca moje konfiguracje powłoki były dość proste ( głównie a .bashrclub .bash_profileniektóre aliasy), ale przerabiałem je tak, aby uzyskać inne zachowanie w zależności od tego, czy używam zsh i bash. Najpierw źródłowy plik konfiguracyjny powłoki, który powinien działać na cokolwiek, a następnie specjalizują się w konkretnej używanej powłoce (odsyłam do tego dowiązanie symboliczne).

Byłem dzisiaj zaskoczony, kiedy lsprzestałem pracować. Okazało się, że podczas refaktoryzacji .bashrcistniał alias

alias ls='ls --color=always'

to było zepsute lsw bash na terminalu w OSX. Kiedy zobaczyłem, że BSD lslubi -Gkolory, ale GNU (lub cokolwiek było na Ubuntu) --color, było jasne, że całkiem sporo opcji się różni.

Moje pytanie brzmi: jaki jest najlepszy sposób na uwzględnienie różnic w opcjach i takich między rdzeniami BSD i GNU? Czy powinienem testować zmienną env w ifblokach, aby zobaczyć, jaki system operacyjny jest używany i zastosować prawidłowe zachowanie? Czy może bardziej sensowne jest tworzenie osobnych plików konfiguracyjnych dla każdego systemu operacyjnego?

Chociaż odpowiedzi na te pytania mogą być subiektywne, wydaje się, że podsumowanie zakresu różnic między rdzeniami BSD i GNU i strategie obejścia ich w celu umożliwienia używania ogólnej konfiguracji na większości * nix byłyby dość obiektywne.

labirynt
źródło
Zmiana pocisków niczego nie naprawi i ls -cróżni się od ls --color. Zredagowałem twoje pytanie, aby naprawić
Mikel

Odpowiedzi:

9

Jedynym niezawodnym sposobem pisania skryptów obsługujących różne systemy operacyjne jest używanie tylko funkcji zdefiniowanych przez POSIX.

W przypadku takich rzeczy, jak osobiste konfiguracje powłoki, możesz użyć hacków, które pasują do konkretnego przypadku użycia. Coś takiego jak poniżej jest brzydkie, ale osiągnie cel.

if ls --version 2>/dev/null | grep -q 'coreutils'; then
    alias ls='ls --color=always'
else
    alias ls='ls -G'
fi
Jordan
źródło
Bawiłem się różnymi metodami i myślę, że twoje „brzydkie” rozwiązanie jest całkiem dobre, a nawet nie takie brzydkie. Jak się okazuje, wcześniej nie zauważyłem niedopasowania opcji ls, ponieważ korzystałem z jądra GNU z portów. Oto przykład, dlaczego wykonanie „if” na $ OSTYPE może nie przynieść pożądanych rezultatów.
labirynt
Czy istnieje sposób na stłumienie błędu wynikającego z „if ls --version”, gdy jądra GNU nie są obecne (ale nadal mogą testować je pod kątem Coreutils)?
labirynt
Och, nieważne, czy pomijać błąd. Po prostu przekierowuję stderr do / dev / null przed potokowaniem do grep i działa tak, jak bym chciał.
labirynt
3
Zamiast szukać coreutilswyraźnie, dlaczego nie po prostu przetestować, czy flaga koloru działa, np if ls --color=auto -d / >/dev/null 2>&1; then ....
Mikel
@mikel, jeśli martwisz się tylko kolorem (jak w przykładzie), to dobrze. Jeśli zależy Ci również na innych funkcjach, przydatne jest sprawdzenie Coreutils.
Jordan
3

Zaśmiecanie kodu ifinstrukcjami, aby wykonać zmianę typu coreutils , działa, jednak czystym rozwiązaniem programistycznym do obsługi różnych typów jest użycie polimorfizmu . Ponieważ jest to Bash, nie mamy polimorfizmu per se, ale mam do czynienia z metodą, która może go sfałszować. Jedynym wymaganiem jest .bashrczorganizowanie pliku itp. W funkcje.

Najpierw tworzę test dla typu platformy Coreutils :

get_coreutils_platform() {
    local ls_version="$(ls --version 2>/dev/null)"
    if [[ "$ls_version" == *"GNU coreutils"* ]]; then
        echo gnu
    else
        echo bsd
    fi
}

Następnie możemy wysłać w zależności od typu:

platform=$(get_coreutils_platform)
define_standard_aliases_$platform
configure_shell_vars_$platform

Oto implementacja BSD :

define_standard_aliases_bsd() {
    define_standard_aliases
}

configure_shell_vars_bsd() {
    configure_shell_vars
    export CLICOLOR=1
}

(Uwaga: używamy tej CLICOLORzmiennej do włączania kolorów zamiast użycia alias, który wydaje się mniejszy)

I realizacja GNU :

define_standard_aliases_gnu() {
    define_standard_aliases
    alias ls='ls --color=auto'
}

configure_shell_vars_gnu() {
    configure_shell_vars
}

Dla kompletności, oto przykładowa implementacja „abstrakcyjnej bazy”:

define_standard_aliases() {
    alias ll='ls -l'
    alias l.='ls -d .*'
}

configure_shell_vars() {
    export EDITOR=vim
}
Michael Kropat
źródło
Jest to o wiele czystsze, chyba że korzystasz z 0,1% systemów z np. GNU ls, ale nie jest zainstalowany GNU cat (może jest naprawdę stary i mają pliki fileutils, ale nie textutils). Kusiłbym lsraczej cat, aby użyć go w twoim dyspozytorze , zwłaszcza, że ​​żaden z twoich pseudonimów nie obejmuje cat.
Mikel
Nie powinieneś także potrzebować --color=autodrugiego i trzeciego aliasu, ponieważ pierwszy alias dodaje tę opcję ls.
Mikel
1
@Mikel whoa, całkowicie nie zdawałem sobie sprawy, że aliasto jest rekurencyjne. To pozwala mi uprościć przykład.
Michael Kropat
Dużo lepiej. :-)
Mikel
0

Nie jest to bezpośrednia odpowiedź na twoje pytanie, ale mam skrypty otoki do obsługi takich rzeczy, a nie dodatkowych komplikacji w .bashrc Na przykład tutaj jest mój skrypt l, który obsługuje twoją sprawę tutaj na wiele platform:

http://www.pixelbeat.org/scripts/l

Pádraig Brady
źródło