zsh(やshやbash)でパス系環境変数の重複を除去する

魚へんのつく漢字は非常にたくさんあって、よく雑学問題とかになるんですが、実際のところいくつあるんでしょう。Unicodeの文字表で調べてみたところ、魚へんのつく漢字は394種類ありました。実際はもっとあるんでしょうが、すごいですね。

さて、tmuxを使っていたり、シェル設定を書き換えてsourceしたりなど、PATHやLD_LIBRARY_PATHなどのパス系環境変数の記述が重複してしまうことがよくあります。
これを解決するためのメモ。
参考はこちら。というか完全にそのまま。
zsh で環境変数 LD_LIBRARY_PATH、INCLUDE などの重複パスを除去する – キーボードをたたくとき

zshrcやzshenvに下記のような記述をすればOKです。

typeset -T LD_LIBRARY_PATH ld_library_path; typeset -U ld_library_path
typeset -T LIBRARY_PATH library_path; typeset -U library_path
typeset -T CPATH cpath; typeset -U cpath

どういう意味かは参考サイトの通りです。

また、特にPATHなどに関しては以下の記述で重複除去ができます。

typeset -U path cdpath fpath manpath

ところで、パス記述の重複ってパフォーマンスには影響するのかな。
つまり、実際のパス探索の段階で、すでに見たところをまた見に行ったりするんでしょうか。
だとすると重複除去は絶対必要ですねー。

あと、bashで同じことをしたい場合はどうすればいいんでしょう。
こんなかんじで重複除去自体はできなくはないですが、

$ PATH=c:b:c:a:b:a
$ PATH=`echo $PATH | sed "s/:/\n/g" | sort -u | paste -sd ":"`
$ echo $PATH
a:b:c

記述順が変化してしまい、実際のパス探索の順序が変わってしまい、イケてないかんじです。
力技でできないことはないけど・・・スマートにできないものか。

追記。bashやshでの重複除去を力づくでやってみたので、興味があれば続きを参照。

力づくで重複除去やるシェルスクリプト書いてみた。
bashの場合。ハイライト部分はzshやsh版との違いのある部分。

#!/bin/bash

TMP=(`echo $PATH | sed "s/:/ /g"`)
RESULT=${TMP[0]}

for P in ${TMP[@]}; do
    if test $(echo $RESULT | grep -c $P) -eq 0; then
        RESULT=$RESULT:$P
    fi
done
export PATH=$RESULT

うごかすと、実際のパス探索順を保って重複除去できていて、イケてる感じです。
ただし見ての通り、例えばPATHが空の場合などの例外パターンのハンドリングはほとんどしていません。

$ PATH=c:a:b:c:b:a
$ ./uniqpath.sh
$ echo $PATH
c:a:b

shの場合。

#!/bin/sh

TMP=`echo $PATH | sed "s/:/ /g"`
RESULT=`echo $TMP | sed "s/\s.\+\$//g"`
#RESULT=`echo $TMP | sed "s/ /\n/g" | head -n 1`  #これでも可

for P in $TMP; do
    if test $(echo $RESULT | grep -c $P) -eq 0; then
        RESULT=$RESULT:$P
    fi
done
export PATH=$RESULT

特に意味はないけどzsh版。ほとんどbash版と同じだけど、配列の扱いが微妙に違うため・・・

#!/bin/zsh

TMP=(`echo $PATH | sed "s/:/ /g"`)
RESULT=$TMP[1]

for P in ${TMP[@]}; do
    if test $(echo $RESULT | grep -c $P) -eq 0; then
        RESULT=$RESULT:$P
    fi
done
export PATH=$RESULT

シェルの違いによるびっみょーな挙動の違い、しんどい。。
RESULTの初期値は、最終的なPATHの先頭や末尾にコロンがつくのがイケてないので、番人として設定してるわけです。そこ気にしないならもっとすっきりいきそう。

おさかなを自称しながらfishで試さない点がオチです。

コメントを残す

メールアドレスが公開されることはありません。