rcmdnk's blog

icon200_200_200

BashやZshで設定ファイルである.bashrc.zshrcをちょっと変更して 再び読み込む場合、 PATHの値などは基本付け加えていく様な設定になってるため、 読み込む度に同じPATHが付け加えられていってやたら長いPATHの値になったりしてしまいます。

そういったことを避けるために最初にちょっと付け加えておく設定について。

Sponsored Links

.bashrc/.zshrcでのPATHなどの設定

.bashrc/.zshrc の中で

export PATH=/home/USER/bin:$PATH

みたいな設定をして自分用のPATHを追加する事があると思います。

この設定のまま.bashrc/.zshrcを再び読み込むと

$ echo $PATH
/home/USER/bin:/home/USER/bin:...

みたいに同じPATHが重複してしまいます。 1つくらいなら何度か読み込み直してもさほど気にならないかもしれませんが、 いくつか加える様な設定をしていると一度source ~/.bashrcとかするだけで PATHの値が無駄にものすごく長くなります。

実用上それほど困らないし、そもそも.bashrc/.zshrcを再読込することはそれ程ないので 気にしない人も多いかと思いますが、 ちょっと気になったのでこれを避ける様な設定を.bashrc/.zshrcに加えてみました。

_reset_path

.bashrc/.zshrcの一番最初に次の様な設定を書きます。

.bashrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function _reset_path {
  local p
  for p in PATH LD_LIBRARY_PATH PYTHONPATH PKG_CONFIG_PATH;do
    local ip=$(eval echo "\$INIT_$p")
    if [ -z "$ip" ];then
      # Set initial values
      eval export INIT_$p="\$$p"
    else
      # Reset paths
      eval export $p="$ip"
    fi
  done
}
_reset_path

関数にせずにそのまま書いても良いですが、 他で使えることもあるかもしれないということで関数に。

普段使うものでもないので_で始まる関数名にしています。

やっていることは初期値のPATHの値をINIT_PATHという値に保存しておく、ということ。

一番最初に.bashrc/.zshrcが読み込まれた時はINIT_PATH の値は無いのでこの時の値をINIT_PATHに保存します。

以降、.bashrc/.zshrcが読み込まれた時には このINIT_PATHの値に初期化して.bashrc/.zshrc を読み始めます。

これで常に.bashrc/.zshrcを読む際にはPATHは同じ初期値から始まるので 余計な重複を避けられます。

LD_LIBRARY_PATHなども同様に重複を避ける設定として入れてあります。

PATHを追加する時のもチェックする

システムによって.bashrc/.zshrcを読み込む前に設定されているPATHの値が違ったり、 また、.bashrcでは/etc/bashrcがあればそれを読み込む様にしていますが その中でのPATHの設定が違ったりします。

/usr/local/binなどのPATHを一通り追加しておきたいのですが、 場合によってはそれらの値が既に入っている時もあります。

そういった時に重複を避けるために以下の様にチェックしながら追加することをしています。

.bashrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# PATH, LD_LIBRARY_PATH under HOME
export x86_64=0
if uname -a|grep -q x86_64;then
  export x86_64=1
fi
for p in "" "/usr" "/usr/local" "$HOME" "$HOME/usr" "$HOME/usr/local";do
  if ! echo "$PATH"|grep -q -e "^$p/bin" -e ":$p/bin";then
    export PATH="$p/bin${PATH:+:$PATH}"
  fi
  if ! echo "$LD_LIBRARY_PATH"|grep -q -e "^$p/lib" -e ":$p/lib";then
    export LD_LIBRARY_PATH="$p/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
  fi
  if ! echo "$PYTHONPATH"|grep -q -e "^$p/lib" -e ":$p/lib";then
    export PYTHONPATH="$p/lib/python$p/lib:${PYTHONPATH:+:$PYTHONPATH}"
  fi
  if ! echo "$PKG_CONFIG_PATH"|grep -q -e "^$p/lib/pkgconfig" -e ":$p/lib/pkgconfig";then
    export PKG_CONFIG_PATH="$p/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
  fi
  if [ "$x86_64" = 1 ];then
    if ! echo "$LD_LIBRARY_PATH"|grep -q -e "^$p/lib64" -e ":$p/lib64";then
      export LD_LIBRARY_PATH="$p/lib64${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
    fi
    if ! echo "$PKG_CONFIG_PATH"|grep -q -e "^$p/lib64/pkgconfig" -e ":$p/lib64/pkgconfig";then
      export PKG_CONFIG_PATH="$p/lib64/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
    fi
  fi
done

それぞれPATHなどに対して、/usr/binなどがPATH中にあるかどうかチェックして なければ追加、ということをやっています。 ("^$p/bin"は先頭にある場合、":$p/bin"は途中にある場合。)

後に追加するもののが優先度が高いので$HOME/usr/local/binPATHでは一番優先度の高いものになります。

もしかすると/usr/local/binがなくて$HOME/usr/local/bin が初期値として入っているシステム、なんてのもあるかもしれません。 その場合にはちょっとこのやり方だと自分の思い通りの優先度にはならないので その場合はちょっと工夫しないといけませんが、 まあ基本的に上の順序を覆す様な初期設定があるシステムは今のところ見てません。

もし、作業中に新たにソフトをインストールする、という可能性がゼロであるならば、

.bashrc
1
2
3
4
5
6
7
8
for p in "" "/usr" "/usr/local" "$HOME" "$HOME/usr" "$HOME/usr/local";do
  if [ -d $p/bin ];then
    if ! echo "$PATH"|grep -q -e "^$p/bin" -e ":$p/bin";then
      export PATH="$p/bin${PATH:+:$PATH}"
    fi
  fi
  ...
done

みたいにして該当のディレクトリがある場合だけPATHを追加する、とすると より無駄のないなPATHにすることも出来ます。

Sponsored Links
Sponsored Links

« Brew-fileでの記述順の整理 .bashrc/.zshrcでマシンローカルな設定等を外部ファイルから読み込む設定 »