なぜそんなことがしたいの?
シェルスクリプトでbash環境にfish環境作りたい。
fishを入れるまではいいけどその後のfish操作が難しい
#!/bin/bash
# fish install
cd /etc/yum.repos.d/
wget http://download.opensuse.org/repositories/shells:fish:release:2/CentOS_7/shells:fish:release:2.repo
yum install fish -y
# デフォルトshellへ
which fish | xargs chsh -s
# fisherman
curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisherman
fisher up # bashにはないよ
シバン | シェバン
複数書いたら以降はそれにならないかなーっと
#!/bin/bash
hogehoge
#!/bin/fish
hugahuga
まあならない。Rubyとかはシバンを見て呼び飛ばしてくれるから、
Perl, Python 及び Ruby スクリプトにおける正しいshebangの書き方 - Qiita
起動されたshは2行目のexecでRubyに飛び、Rubyは3行目までを読み飛ばすという寸法である。
#!/bin/bash
hogehoge
fish readlink -f $0 # スクリプト内でのcd対策に絶対パスで
exit 0
#!/bin/fish
hugahuga
bash で ファイルの絶対パスを得る - Qiita コメント:#comment-10d1b710bcf7df114cb7
こんな感じのを書いたけど、まあfishのシェバンまで読み飛ばすことはなく、頭から再実行するよねと。
実行中シェル判定
じゃあ自身を別シェルで呼び出すまではいいとして、実行中のシェル名を見てifで分岐すればいいんじゃない?
文法上の問題はあるだろうけど、インタプリタで毎行解析?だろうから通過しなければいいし、デフォルト設定だと失敗しても処理が継続するのがシェルの特徴?だから?、なんとかなるかも。
bashにはSHELL変数があるみたいだし。
と思って調べて、
現在使っているシェルの名前を知る方法 - 揮発性のメモ
や
現在の shell を shellscript の中から確認する(Linux, BSD 両対応) - tkuchikiの日記
を見て
#!/bin/bash
echo 'start'
echo `readlink /proc/$$/exe`
if [ `readlink /proc/$$/exe | grep bash` ] ; then
echo "bash"
fish `readlink -f $0`
elif [ `readlink /proc/$$/exe | grep fish` ] ; then
echo "fish"
fisher up
fi
みたいにしたんだけど、fishがifや$$のは使えないよーってなって無理でした。
POSIX互換?なシェルで基本文法が同じならできるかもしれない?
fishはPOSIX互換ではないらしい。
ログインシェルは bash のまま fish を利用する - Qiita
この問題はログインシェルを一時的に bash に戻すことで解決できました。
ですが、rsync に限らず、何らかの形でシェルに依存しているプログラムは、そのシェルが POSIX 互換であることを前提としています。fish は POSIX 非互換なので、いつまた同じような問題に遭遇するかわかりません。
最終的に
bashの中で一コマンドごとにfishを呼び出すのでした。
手を出すにはまだ早い領域でした。
#!/bin/bash
# fishインストール
# 毎回呼び出し
fish -c 'fisher up'
fish -c 'fisher install spin'