PATHにパスを正しく追加する方法は?


923

PATH環境変数のどこに新しいパスを追加する必要があるのか​​疑問に思っています。これは.bashrc(たとえば)編集することで達成できることは知っていますが、これを行う方法は明確ではありません。

こちらです:

export PATH=~/opt/bin:$PATH

それともこれ?

export PATH=$PATH:~/opt/bin

printf '\ nPATH = $ PATH: "追加するパス" \ nexport PATH \ n' >>〜/ .bashrc
Sudoer 14年


すでにいくつかのパスが追加されている場合、たとえばPATH=$PATH:$HOME/.local/bin:$HOME/bin、:egで区切ることで別のパスを追加できますPATH=$PATH:$HOME/.local/bin:$HOME/bin:/home/ec2-user/pear/bin
サンディーパンナス

2
これらの回答はすべての種類のLinuxで機能しますか?
ウンゲホイヤー

回答:


1033

シンプルなもの

PATH=$PATH:~/opt/bin

または

PATH=~/opt/bin:$PATH

~/opt/bin末尾に追加するか(複数のディレクトリに同じ名前のプログラムがある場合に他のすべてのディレクトリの後に検索する)、先頭に追加する(他のすべてのディレクトリの前に検索する)かによって異なります。

複数のエントリを同時に追加できます。PATH=$PATH:~/opt/bin:~/opt/node/binまたは注文作業のバリエーションは問題ありません。export追加の複雑さがあるため、行の先頭に置かないでください(以下の「bash以外のシェルに関する注意」を参照)。

PATHさまざまなコンポーネントでビルドされている場合、エントリが重複する可能性があります。Unix whichコマンドで検出されるホームディレクトリパスを追加する方法を参照してくださいそして、awkコマンドで重複の$ PATHエントリを削除し、重複を追加しないか、それらを削除します。

いくつかのディストリビューション~/binは、PATHが存在する場合、自動的にPATHに入れられます。

どこに置くか

変更する行を入れPATH~/.profile、またはで~/.bash_profileそれはあなたが持っているものだ場合。

これ~/.bash_rcはどのプログラムによっても読み取られず~/.bashrc、bashの対話型インスタンスの構成ファイルです。で環境変数を定義しないでください~/.bashrcPATHis ~/.profile(または~/.bash_profilebash以外のシェルを気にしない場合)などの環境変数を定義する適切な場所。参照してください彼らと私は1つを使用する必要があるとの違いは何ですか?

入れてはいけない/etc/environmentか、~/.pam_environmentこれらのファイルをシェルされていない、あなたは次のように置換を使用することはできません$PATHがインチ これらのファイルでは、変数をオーバーライドすることはできますが、追加することはできません。

一部のシステムスクリプトの潜在的な合併症

export変数が既に環境にある場合は必要ありません。変数の値の変更はすべて環境に反映されますPATH。¹はほとんど常に環境にあります。すべてのUNIXシステムは、非常に早い段階で設定します(通常、実際には最初のプロセスで)。

ログイン時に、PATHすでに環境内にあり、すでにいくつかのシステムディレクトリが含まれていることに依存できます。ある種の仮想環境のセットアップ中に早期に実行される可能性のあるスクリプトを作成している場合、それがPATH空でないこととエクスポートされていることを確認する必要があります。PATHまだ設定PATH=$PATH:/some/directoryPATH:/some/directoryていない場合、先頭は現在のディレクトリを意味し.:/some/directoryます(など)。

if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi

bash以外のシェルに関する注意

bashの、kshのとzshのでは、export特別な構文で、両方PATH=~/opt/bin:$PATHexport PATH=~/opt/bin:$PATHも、正しいことを行います。他のBourne / POSIXスタイルのシェル(ダッシュ(/bin/sh多くのシステムにあります)など)ではexport、通常のコマンドとして解析されます。これは、2つの違いを意味します。

そのため、ダッシュのようなシェルでexport PATH=~/opt/bin:$PATHPATH、リテラル文字列の~/opt/bin/:PATHに最初のスペースまでの値が続きます。 PATH=~/opt/bin:$PATH(裸の割り当て)は引用符必要とせず、正しいことを行います。あなたが使用したい場合はexport、ポータブルスクリプトで、次のように記述する必要があるexport PATH="$HOME/opt/bin:$PATH"、またはPATH=~/opt/bin:$PATH; export PATH(あるいはPATH=$HOME/opt/bin:$PATH; export PATH受け入れなかったBourneシェル均等への移植のためexport var=valueとチルダ展開をしませんでしたが)。

¹ これは、Bourneシェル(最新のPOSIXスタイルのシェルではなく、実際のBourneシェルの場合)には当てはまりませんでしたが、最近ではそのような古いシェルに遭遇する可能性は非常に低いです。


それでもエクスポートの複雑さを理解することはできません。簡素化していただけますか?
priojeet priyom

@priojeetpriyom簡単な説明:必要ありませんexport
ジル

完全に詳細なこの回答をありがとう。「〜/ .bashrcで環境変数を定義するべきではありません」と言いますが、残念ながら、システムにインストールしたパスを変更するプログラム(FZFとRustの貨物)の100%がを変更します.bashrc。FZFもRustで書かれているため、Rustのパターンに従っていると思います。
icc97

83

どちらの方法でも機能しますが、同じことは行いません。の要素はPATH左から右にチェックされます。最初の例では、実行可能ファイルin ~/opt/binが、インストールされている実行可能ファイルより優先され/usr/binます。

特に、安全性の観点から、パスを前面に追加するのは危険です。なぜなら、誰かがあなたへの書き込みアクセス権を得ることができる場合~/opt/bin、例えば、lsそこに別のものを置くことができます。/bin/ls気づかずに。ここで、sshまたはブラウザまたは選択について同じことを想像してください...(パスに。


6
ただし、独自のカスタマイズされたバージョンを使用lsする場合は、の前のディレクトリに配置する必要があります/bin
バーマー

16
またはエイリアスls = myls
waltinator

37

私は質問2と混同しています(関連のない問題のために質問から削除されたため):

別の行にさらにパスを追加する実用的な方法は何ですか?当初はこれでうまくいくと思いました。

export PATH=$PATH:~/opt/bin
export PATH=$PATH:~/opt/node/bin

ただし、2番目の割り当てではが追加されるだけ~/opt/node/binでなく、PATH以前に割り当てられた全体も追加 されるためです。

これは可能な回避策です。

export PATH=$PATH:~/opt/bin:~/opt/node/bin

しかし、読みやすくするために、1つのパスに1つの割り当てが必要です。

あなたが言うなら

PATH=~/opt/bin

それはですすべての PATHにされること。PATHは単なる環境変数であり、PATHに追加する場合は、希望する内容で変数を再構築する必要があります。つまり、質問2の例として挙げたのは、私が質問の要点を完全に逃していない限り、まさにあなたがやりたいことです。

私はコードで両方のフォームを使用します。私が作業しているすべてのマシンにインストールする汎用プロファイルがあります。これは、欠落している可能性のあるディレクトリに対応するためです。

export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11
# add optional items to the path
for bindir in $HOME/local/bin $HOME/bin; do
    if [ -d $bindir ]; then
        PATH=$PATH:${bindir}
    fi
done

2
質問2の例については正しいです、それは動作します。私のシステム上の別のPATH関連の問題は私を混乱させました。そのために残念。
パオロ

26

防弾の追加/追加の方法

追加と追加の選択には、多くの考慮事項があります。それらの多くは他の回答でカバーされているので、ここでは繰り返しません。

重要な点は、システムスクリプトがこれを使用していない場合でも(なぜだろうか)* 1$HOME/binPATH環境変数にパス(たとえば、)を追加する防弾方法は

PATH="${PATH:+${PATH}:}$HOME/bin"

(の代わりにPATH="$PATH:$HOME/bin")追加するためと

PATH="$HOME/bin${PATH:+:${PATH}}"

の代わりに(の代わりにPATH="$HOME/bin:$PATH"

これにより、$PATH最初は空の場合の誤った先頭/末尾のコロンが回避され、望ましくない副作用が発生し、見つけにくい悪夢なる可能性があります(この答えは簡単にケースをawk扱います)。

説明シェルパラメーター拡張から):

${parameter:+word}

parameterがnullまたは未設定の場合、何も置換されませんword。それ以外の場合は、の拡張が置換されます。

したがって、次のように${PATH:+${PATH}:}展開されます。1)PATHnullまたは未設定の場合は何も、2)設定されている${PATH}:場合PATH

:これはbash用です。


* 1devtoolset-6/enable実際にこれを使用するようなスクリプトがあることがわかりました。

$ cat /opt/rh/devtoolset-6/enable
# General environment variables
export PATH=/opt/rh/devtoolset-6/root/usr/bin${PATH:+:${PATH}}
...

24

Linuxは、$PATH環境変数を使用して実行可能な検索パスを決定します。ディレクトリ/ data / myscriptsを$PATH環境変数の先頭に追加するには、次を使用します。

PATH=/data/myscripts:$PATH

そのディレクトリをパスの最後に追加するには、次のコマンドを使用します。

PATH=$PATH:/data/myscripts

ただし、スクリプト内で環境変数を設定すると、その変更はスクリプト内でのみ有効になるため、前述の方法では十分ではありません。この制限を回避する方法は2つしかありません。

  • スクリプト内で環境変数をエクスポートすると、スクリプトによって呼び出されるプログラム内で環境変数が有効になります。スクリプトを呼び出したプログラム内では効果がないことに注意してください。
  • スクリプトを呼び出すプログラムが呼び出しの代わりに含めることによってそうする場合、スクリプト内の環境の変更は呼び出しプログラム内で有効です。このような組み込みは、ドットコマンドまたはソースコマンドで実行できます。

例:

$HOME/myscript.sh
source $HOME/myscript.sh

包含には、基本的に「呼び出し」スクリプトに「呼び出された」スクリプトが組み込まれます。Cの#includeのようなものです。したがって、「呼び出し」スクリプトまたはプログラム内で効果的です。ただし、もちろん、呼び出し元プログラムによって呼び出されるプログラムやスクリプトでは効果的ではありません。コールチェーン全体で有効にするには、エクスポートコマンドで環境変数の設定に従う必要があります。

例として、bashシェルプログラムには、ファイル.bash_profileの内容が含まれます。.bash_profileに次の2行を配置します。

PATH=$PATH:/data/myscripts
export PATH

これらの2行のコードをbashプログラムに効果的に配置します。その$HOME/myscript.shため、bash内では、$ PATH変数にが含まれます。export ステートメントのため、bashによって呼び出されるプログラムはすべて変更された$PATH変数を持ちます。また、bashプロンプトから実行するプログラムはbashによって呼び出されるため、bashプロンプトから実行するすべてのプログラムに対して新しいパスが有効になります。

一番下の行は、新しいディレクトリをパスに追加するには、シェルに含まれるスクリプト内で$ PATH環境変数にディレクトリを追加または追加し、$PATH環境変数をエクスポートする必要があるということです。

詳細はこちら


19

しばらくの間、私は2つの機能をpathadd持ち続け、pathrm重複を心配することなくパスに要素を追加できるようにしました。

pathadd単一のパス引数とオプションのafter引数を取ります。オプションの引数は、指定されている場合は追加され、追加されPATHない場合は先頭に追加されます。

ほとんどすべての状況で、パスに追加する場合、おそらくパスに既にあるものを上書きしたいので、デフォルトで先頭に追加することを選択します。

pathadd() {
    newelement=${1%/}
    if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then
        if [ "$2" = "after" ] ; then
            PATH="$PATH:$newelement"
        else
            PATH="$newelement:$PATH"
        fi
    fi
}

pathrm() {
    PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}

これらをPATH環境を変更したいスクリプトに入れれば、すぐにできます。

pathadd "/foo/bar"
pathadd "/baz/bat" after
export PATH

パスが既に存在する場合、パスに追加しないことが保証されています。確認したい場合/baz/batは、最初にあることを確認してください。

pathrm "/baz/bat"
pathadd "/baz/bat"
export PATH

これで、パスを二重化せずに既にパス内にある場合、任意のパスを前面に移動できます。


PATH内のディレクトリの存在を確認するための関連するわかりやすいアプローチ
ワイルドカード

9

他のディストリビューションについて話すことはできませんが、Ubuntuには/ etc / environmentというファイルがあり、これがすべてのユーザーのデフォルトの検索パスです。私のコンピューターは私だけが使用するので、スクリプトに一時的に追加するのでない限り、そこにあるパスに任意のディレクトリを配置します。


6

PATH=/a/b:$PATHパスを追加する「間違った」方法と見なされる場合がありますPATH

  1. 実際にはディレクトリではないパスを追加します。
  2. すでにPATH同じフォームにあるパスを追加します。
  3. 相対パスを追加する(現在の作業ディレクトリを変更すると、実際に検索されるディレクトリが変更されるため)。
  4. すでにPATH別の形式(つまり、シンボリックリンクまたはを使用するためのエイリアス..)にあるパスを追加します。
  5. 4の実行を避ける場合、パスを内のPATH他のエントリをオーバーライドする予定のときに前に移動しないでくださいPATH

この(Bash専用)関数は、上記の状況(例外を除き、以下を参照)で「正しいこと」を行い、エラーコードを返し、人間に素敵なメッセージを出力します。エラーコードとメッセージは、不要な場合は無効にできます。

prepath() {
    local usage="\
Usage: prepath [-f] [-n] [-q] DIR
  -f Force dir to front of path even if already in path
  -n Nonexistent dirs do not return error status
  -q Quiet mode"

    local tofront=false errcode=1 qecho=echo
    while true; do case "$1" in
        -f)     tofront=true;       shift;;
        -n)     errcode=0;          shift;;
        -q)     qecho=':';          shift;;
        *)      break;;
    esac; done
    # Bad params always produce message and error code
    [[ -z $1 ]] && { echo 1>&2 "$usage"; return 1; }

    [[ -d $1 ]] || { $qecho 1>&2 "$1 is not a directory."; return $errcode; }
    dir="$(command cd "$1"; pwd -P)"
    if [[ :$PATH: =~ :$dir: ]]; then
        $tofront || { $qecho 1>&2 "$dir already in path."; return 0; }
        PATH="${PATH#$dir:}"        # remove if at start
        PATH="${PATH%:$dir}"        # remove if at end
        PATH="${PATH//:$dir:/:}"    # remove if in middle
    fi
    PATH="$dir:$PATH"
}

例外は、この関数はPATH他の手段で追加されたパスを正規化しないため、パスの非正規エイリアスがにあるPATH場合、これは重複を追加します。PATH相対パスは渡されprepathたときに明らかな意味を持ちますが、すでにパスにあるときは、現在の作業ディレクトリが追加されたときの内容がわからないため、すでに存在するパスを正規化しようとすることは危険です。


相対パスに関して:「-r」スイッチを使用するとどうなりますか?これは、最初に絶対パスにせずにパスを追加し、追加する前に絶対パスを探しますか?これがスクリプトの場合、他のシェルで使用できます。機能として持つ利点はありますか?素敵なコード!
ホイジュ

1
@hoijui現在の環境を変更しているため、関数でなければなりません。スクリプトの場合、スクリプトを実行しているサブプロセスの環境を変更し、スクリプトが終了すると、$PATH以前と同じ状態になります。については-r、いや、一般的なツールでそのようなものをサポートしたいので、相対パスは$PATHあまりにも信頼性が低く、奇妙です(あなたのパスは毎回変わるcd!)。
カートJ.サンプソン

5

私(Mac OS X 10.9.5)では/mypathname、ファイルへのパス名(例:)の追加は/etc/paths非常にうまくいきました。

編集する前に、以下をecho $PATH返します。

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

/etc/pathsシェルを編集して再起動すると、$ PATH変数にが追加され/pathnameます。確かに、echo $PATH返します:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname

起こったことは/mypathname$PATH変数に追加されたことです。


3
/ etc / pathsファイル自体を編集するよりも、/ etc / paths.dディレクトリにファイルを追加する方が適切です。
rbrewer

4

PATH環境変数に新しいパスを追加するには:

export PATH=$PATH:/new-path/

この変更を開いたすべてのシェルに適用するには、シェルが呼び出されたときにソースとなるファイルに追加します。別のシェルでは、これは次のようになります。

  • Bashシェル:〜/ .bash_profile、〜/ .bashrcまたはprofile
  • Kornシェル:〜/ .kshrcまたは.profile
  • Zシェル:〜/ .zshrcまたは.zprofile

例えば

# export PATH=$PATH:/root/learning/bin/
# source ~/.bashrc
# echo $PATH

上記の出力で提供されたパスを確認できます。


4

ここに私の解決策があります:

PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

トレーリングを残さない素敵な簡単なライナー :


1
-bash:awk:そのようなファイルまたはディレクトリなし-bash:sed:そのようなファイルまたはディレクトリなし
-davidcondrey

1
@davidcondrey-awkとsedは非常に一般的な外部コマンドです。この回答は同じことを達成するための純粋なbash方法を提供するので、awkおよび/またはsedが存在しない(またはそれぞれのディレクトリがパスにない!)場合
でも機能します-sancho.s
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.