シェル構成スクリプトでは、GNUと比較したBSD上のcoreutilsの違いをどのように説明できますか?


9

今月までは、シェルの構成はかなり単純です(主に、.bashrcまたは.bash_profileいくつかのエイリアスを使用して)。しかし、zshとbashのどちらを使用しているかによって異なる動作が得られるように、リファクタリングしています。彼らは最初に何でも機能する一般的なシェル構成ファイルを調達し、次に使用されている特定のシェルに特化します(私はこれにシンボリックリンクします)。

今日lsは仕事をやめてびっくりしました。リファクタリング中に.bashrcエイリアスがあったことが判明しました

alias ls='ls --color=always'

それがために何かを壊したlsOSXのターミナル上のbashで。BSD ls-G色が好きだが、GNU(またはUbuntuにあるものは何でも)が好きだ--colorと思ったら、かなりの数のオプションが異なることは明らかでした。

私の質問は、BSDとGNU coreutilsの間のオプションの違いなどを説明する最良の方法は何ですか?ifブロックでenv変数をテストして、使用されているOSを確認し、正しい動作を適用する必要がありますか?または、OSごとに個別の構成ファイルを作成する方が理にかなっていますか?

これらの質問への回答は主観的である可能性がありますが、BSDとGNU coreutilsの違いの範囲の概要と、ほとんどの* nixで汎用構成を使用可能にするためにこれらを回避する戦略はかなり客観的なようです。


シェルを変更しても何も修正されず、とls -cは異なりls --colorます。修正するために質問を編集しました。
ミケル2014年

回答:


9

異なるオペレーティングシステムをサポートするスクリプトを作成する唯一の信頼できる方法は、POSIXで定義されている機能のみを使用することです。

個人のシェル構成などの場合、特定のユースケースに適合するハックを使用できます。次のようなものは醜いですが、目標を達成します。

if ls --version 2>/dev/null | grep -q 'coreutils'; then
    alias ls='ls --color=always'
else
    alias ls='ls -G'
fi

私はさまざまな方法を試してきましたが、あなたの「醜い」解決策はかなり見栄えがよく、それほど醜いとは思いません。結局のところ、PortsのGNU coreutilsを使用していたため、以前のlsのオプションの不一致に気づかなかった。これは、$ OSTYPEで「if」を実行すると、望ましい結果が得られない場合がある理由の例です。
ラビリンス

GNU coreutilsが存在しない(ただし、coreutilsをテストできる)場合に、「if ls --version」から発生するエラーを抑制する方法はありますか?
ラビリンス

ああ、エラーの抑制については気にしないでください。gderにパイプする前にstderrを/ dev / nullにリダイレクトするだけで、希望どおりに機能します。
ラビリンス

3
coreutils明示的に探すのではなく、色フラグが機能するかどうかだけをテストするのはなぜですかif ls --color=auto -d / >/dev/null 2>&1; then ...
ミケル2014年

@mikel(例のように)が色だけに関心がある場合は問題ありません。他の機能も気にする場合は、coreutilsのチェックが役立ちます。
ヨルダン2014年

3

coreutilsifのタイプを切り替えるステートメントをコードに散らばらせても機能しますが、さまざまなタイプを処理するためのクリーンなプログラミングソリューションは、ポリモーフィズムを使用することです。これはBashなので、それ自体にはポリモーフィズムはありませんが、私はそれを偽造する方法をいじっています。唯一の要件は、.bashrcファイルなどを関数に整理することです。

まず、coreutilsプラットフォームタイプのテストを作成します。

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

次に、タイプに基づいてディスパッチできます。

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

ここだBSDの実装は:

define_standard_aliases_bsd() {
    define_standard_aliases
}

configure_shell_vars_bsd() {
    configure_shell_vars
    export CLICOLOR=1
}

CLICOLOR色をオンにするために、変数を使用していることに注意してください。代わりにalias、よりクリーンなように見えます)

そして、GNUの具象化:

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

configure_shell_vars_gnu() {
    configure_shell_vars
}

完全を期すために、「抽象ベース」のサンプル実装を以下に示します。

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

configure_shell_vars() {
    export EDITOR=vim
}

これは、たとえばGNU lsがインストールされていて、GNU catがインストールされていないシステムの0.1%を使用している場合を除いて、はるかにクリーンです(たぶんそれは本当に古く、fileutilsはあるがtextutilsはありません)。特にエイリアスが含まれていないlsためcat、ディスパッチャではなくを使用したくなりますcat
ミケル2014年

また、--color=auto最初のエイリアスはそのオプションをに追加するため、2番目と3番目のエイリアスは必要ありませんls
ミケル2014年

1
@Mikel whoa、私はそれaliasが再帰的であることを完全に理解していませんでした。これにより、例をはるかに簡単にすることができます。
Michael Kropat 2014年

ずっといい。:-)
ミケル

0

あなたの質問への直接の回答ではありませんが、.bashrcの余分な複雑さではなく、このようなことを処理するラッパースクリプトがあります。たとえば、ここではクロスプラットフォームの方法でケースを処理するlスクリプトを示します。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.