web-dev-qa-db-ja.com

zshまたはbashを使用してシェルを自己検出させる方法

ユーザーが使用しているシェルを確認する方法について質問があります。ユーザーがzshを使用している場合は.zshrcにPATHを配置し、bashを使用する場合は.bashrcに配置するスクリプトを想定します。それに応じてrvmrcを設定します。

#!/usr/bin/env bash
export PATH='/usr/local/bin:$PATH'" >> ~/.zshrc
source ~/.zshrc

私は次のことを試しましたが、うまくいきません:(

if [[ $0 == "bash ]]; then
  export PATH='/usr/local/bin:$PATH'" >> ~/.bashrc
Elif [[ $0 == "zsh" ]]; then
  export PATH='/usr/local/bin:$PATH'" >> ~/.zshrc
fi

# ... more commands ...

if [[ $0 == "bash ]]; then
  [[ -s '/Users/`whoami`/.rvm/scripts/rvm' ]] && source '/Users/`whoami`/.rvm/scripts/rvm'" >> ~/.bashrc
  source ~/.bashrc
Elif [[ $0 == "zsh" ]]; then
  [[ -s '/Users/`whoami`/.rvm/scripts/rvm' ]] && source '/Users/`whoami`/.rvm/scripts/rvm'" >> ~/.zshrc
  source ~/.zshrc
fi
47
Juanito Fatas

警告の言葉:あなたが尋ねたと思われる質問、あなたが尋ねたつもりの質問、そしてあなたが尋ねるべきだった質問は、3つの異なるものです。

「ユーザーが使用しているシェル」はあいまいです。どのシェルがスクリプトを実行しているかを判断しようとしているように見えます。ユーザーがそのスクリプトを編集することを意図していない限り、それは常にスクリプトの#!行に入れたものになりますので、これは役に立ちません。

あなたが尋ねたいと思ったのは、ユーザーのお気に入りのシェルとは何だと思います。これは完全に確実に決定することはできませんが、ほとんどの場合をカバーできます。 Shell環境変数を確認します。 fishzshbashksh、またはtcshが含まれている場合、ユーザーのお気に入りのシェルはおそらくそのシェルです。ただし、これは問題の間違った質問です。

.bashrc.zshrc.cshrcなどのファイルは、シェル初期化ファイルです。環境変数を定義するのに適切な場所ではありません。そこで定義された環境変数は、ユーザーがそのシェルを起動した端末でのみ使用でき、GUIから起動したプログラムでは使用できません。この定義は、ユーザーがサブセッションで行ったカスタマイズも上書きします。

環境変数を定義する適切な場所は、セッションスタートアップファイルです。これは、ユーザーのシェルの選択とはほとんど関係ありません。残念ながら、環境変数を定義する単一の場所はありません。多くのシステムで、~/.profileは機能しますが、これは普遍的ではありません。 https://unix.stackexchange.com/questions/4621/correctly-setting-environment と、より長い議論のためにそこにリンクしている他の投稿を参照してください。

27
Gilles

シェルがZshの場合、変数$ZSH_VERSIONが定義されます。 Bashと$BASH_VERSIONについても同様です。

if [ -n "$ZSH_VERSION" ]; then
   # assume Zsh
Elif [ -n "$BASH_VERSION" ]; then
   # assume Bash
else
   # asume something else
fi

ただし、これらの変数は、上記のコードを実行するために使用されているシェルを示しているだけです。そのため、ユーザーのシェルでこのフラグメントをsourceする必要があります。

別の方法として、$Shell環境変数(ユーザーの優先シェルへの絶対パスが含まれている必要があります)を使用し、その変数の値からシェルを推測できます。

case $Shell in
*/zsh) 
   # assume Zsh
   ;;
*/bash)
   # assume Bash
   ;;
*)
   # assume something else
esac

もちろん、/bin/sh/bin/bashへのシンボリックリンクである場合、上記は失敗します。

$Shellに依存する場合は、実際にいくつかのコードを実行する方が安全です。

if [ -n "`$Shell -c 'echo $ZSH_VERSION'`" ]; then
   # assume Zsh
Elif [ -n "`$Shell -c 'echo $BASH_VERSION'`" ]; then
   # assume Bash
else
   # asume something else
fi

この最後の提案は、スクリプトの実行に使用されるシェルに関係なく、スクリプトから実行できます。

105
adl

echo $0を実行するだけで、zshの場合は-zshとなり、bashの場合は-bashと表示されます

編集:時々-zshを返し、時にはzshを返します。bashでも同じです。理由はidkです。

42

別の方法として、すべてのシェルで機能するとは限りません。

for x in $(ps -p $$)
do
  ans=$x
done
echo $ans
2
pizza

Gillesからの以前の回答に基づいて、これをどのように行っているかを以下に示します。

if [ -n "$ZSH_VERSION" ]; then
  Shell_PROFILE="$HOME/.zprofile"
else
  Shell_PROFILE="$HOME/.bash_profile"
fi
echo "export VAR1=whatever" >> $Shell_PROFILE
echo "INFO: Refreshing your Shell profile: $Shell_PROFILE"
if [ -n "$ZSH_VERSION" ]; then
  exec zsh --login
else
  source $Shell_PROFILE
fi
1
djangofan

私自身も同様の問題を抱えており、

_Shell="$(ps -p $$ --no-headers -o comm=)"                                                                                                       
if [[ $_Shell == "zsh" ]]; then                                                                                                                  
    read -q -s "?Do it?: "                                                                                                                    
fi                                                                                                                                               
Elif [[ $_Shell == "bash" || $_Shell == "sh" ]]; then                                                                                              
    read -n 1 -s -p "Do it [y/n] "                                                                                                            
fi                                                                                                                                               
0
agathodaimon