web-dev-qa-db-ja.com

PATH変数から重複するエントリを削除します

.bashrcを頻繁に変更してから、ソースを作成します。ただし、ファイルにexport PATH="~/bin:~/Perl5/bin:$PATH"のようなものがある場合、ファイルをソースするたびにPATH環境変数が大きくなります。

たとえば、.bashrcが初めて提供されるとき、PATH変数は~/bin:~/Perl5/bin:/usr/bin:/binで構成されます。

2回目は~/bin:~/Perl5/bin:~/bin:~/Perl5/bin:/usr/bin:/binで構成されます。

3回目は~/bin:~/Perl5/bin:~/bin:~/Perl5/bin:~/bin:~/Perl5/bin:/usr/bin:/binで構成されます。

まだPATHにないものだけを追加する簡単な方法はありますか?

9

ほとんどのディストリビューションの/etc/profileで使用可能なpathmunge()関数を使用します。

pathmunge () {
if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
   if [ "$2" = "after" ] ; then
      PATH=$PATH:$1
   else
      PATH=$1:$PATH
   fi
fi
}

編集zshユーザーの場合、typeset -U <variable_name>はパスエントリを重複排除します。

12
Sam Halicke

私はこの問題を抱えていたので、 StackOverflow の質問にリストされているテクニックの組み合わせを使用しました。以下は、基本スクリプトを変更したくなかったため、すでに設定されている実際のPATH変数を重複排除するために使用したものです。

    tmppath=(${PATH// /@})
    array=(${tmppath//:/ })
    for i in "${array[@]//@/ }"
    do
        if ! [[ $PATH_NEW =~ "$i" ]]; then
            PATH_NEW="${PATH_NEW}$i:";
        fi
    done;
    PATH="${PATH_NEW%:}"
    export PATH
    unset PATH_NEW

これはいつでももう少し最適化できますが、変数が正しく設定されていることを確認するために、何が起こっているかを表示するための追加のコードがオリジナルにありました。注意すべきもう一つのことは、私が以下を実行することです

  1. スペース文字を@文字に置き換えます
  2. 配列を分割する
  3. 配列をループする
  4. 要素文字列内の@文字をスペースに置き換えます

これは、スペースが含まれるディレクトリを確実に処理できるようにするためです(Active Directoryユーザー名を持つSambaホームディレクトリにはスペースを含めることができます!)

3
netniV

1つの文字列のみ:

for i in $(echo $PATH|tr ":" "\n"|sort|uniq);do PATH_NEW="${PATH_NEW}$i:";done;PATH="${PATH_NEW%:}"
1
bindbn

パスを明示的に設定します。

1
Cakemox

これを解決する方法は2つ考えられます。 1つ目は、ベースPATHを明示的に設定する行で.bashrcを開始することです。これにより、ソースを取得するたびに、ディレクトリを追加する前にベースにリセットされます。

たとえば、次を追加します。

# Reset the PATH to prevent duplication and to make sure that we include
# everything we want.
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

または、パスに追加する前にアイテムを確認することもできます。これを行うには、次のようなものを使用します。

if ! [[ $PATH =~ '~/Perl5/bin' ]]
then
    PATH="~/Perl5/bin:$PATH"
fi

ただし、エントリを多く追加する場合、後者は少し繰り返しになる傾向があるので、私は前者に固執する傾向があります。これを使用したいが、多くのエントリを追加することを計画している場合は、それを処理するbash関数を作成するのが賢明です。

注:2番目のオプションは、最新バージョンのbashで記述されている場合にのみ機能する可能性があります。正規表現のサポートはBourneShell(/ bin/sh)機能ではなく、他のシェルには存在しない可能性があります。また、引用符を使用する必要がない場合や、bashの最新バージョンで問題が発生する場合もあります。

1

これが私の解決策です:PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

末尾を残さない素敵な簡単なワンライナー:

0
AJ.