$ PATHのエントリが重複していますか?


45

私は数人の友人のbashrcを調達しています。そのため、$ PATH変数に重複したエントリができてしまいます。開始に時間がかかるコマンドの問題かどうかはわかりません。$ PATHはbashで内部的にどのように機能しますか?PATHを増やすと起動時間が遅くなりますか?




回答:


42

エントリを増やし$PATHても起動は直接遅くなりませんが、シェルセッションで最初に特定のコマンドを実行するたびに遅くなります(bashがキャッシュを保持するため、コマンドを実行するたびに遅くなるわけではありません)。特に遅いファイルシステム(NFS、Samba、または他のネットワークファイルシステム、またはCygwin上)がない限り、スローダウンはほとんど知覚できません。

重複したエントリは、$PATH視覚的に確認するときに少し面倒です。

重複するエントリを追加しないようにするのは簡単です。

case ":$PATH:" in
  *":$new_entry:"*) :;; # already there
  *) PATH="$new_entry:$PATH";; # or PATH="$PATH:$new_entry"
esac

サイドノート:他の誰かのシェルスクリプトを入手するということは、彼が書いたコードを実行することを意味します。つまり、友達はいつでも自分のアカウントにアクセスできます。

サイドノート:.bashrc設定する適切な場所$PATHまたは他の環境変数ではありません。環境変数はで設定する必要があります~/.profile。参照のbashで環境変数を設定するために使用されるべきセットアップファイル?.bashrcと.bash_profileの違い


8
+1:「友人にアカウントへのアクセスを許可する」ことを十分強調することはできません。あなたが危害を加えようとしていなくても、彼らの台本は彼らが必要とするものであり、それをあなたがそれを調達するときにあなたの昼食を食べ続けることができます。
msw

このソリューションで考えられる問題の1つは、$ new_entryが既にPATHの最初のエントリである場合、「:$ new_entry:」が一致しないことです。最初の「:」コロンを除外することで、プロファイルでこれを修正しました。
ジェフバウアー

@JeffBauer問題は見当たりません。私が使用case :$PATH:していないcase $PATHので、それはエントリーが最初か最後であっても、一致していること。
ジル「SO-悪であるのをやめる」

31

awk次のようなものを使用して、PATH変数から重複をクリーンアップする人々を見てきました。

PATH=$(printf "%s" "$PATH" | awk -v RS=':' '!a[$1]++ { if (NR > 1) printf RS; printf $1 }')

それをあなた自身のbashrcに追加してみて、それを実行する前にどこか他のファイルを確実にソースすることができます。

別の方法はpathmergeユーティリティを使用することです。

速度の問題に関しては、これはシェルの起動時間に大きな影響を与えませんが、特にコマンドがパスに見つからず、同じものを繰り返し検索する場合、コマンドのタブ補完を行う時間を節約できますそれを探しているフォルダ。

セキュリティ上の注意:あなたがすべき本当に耳を傾けるジル警告ここセキュリティについてを。別のユーザーが所有するファイルを調達することにより、シェルを起動するたびにユーザーとして独自のコードを実行するための無料パスをそれらのユーザーに提供します。パスワードでそれらのユーザーを信頼していない場合は、シェルファイルを入手しないでください。


6
私はawkワンライナーが好きですが、末尾のORS ':'を出力します。だから私はそれを読むように修正しましたPATH=$(echo "$PATH" | awk -v RS=':' -v ORS=":" '!a[$1]++{if (NR > 1) printf ORS; printf $a[$1]}')
-gkb0986

末尾:は見た目の問題だけではありません。.パスに追加するのと同じです。これは潜在的に危険です。
ウィスバッキー

回答を編集して、gkb0986からの修正を含めました。
ティムレッシャー

@TimLesher私が答えよりも編集したことがない理由は、それが私のために機能しないためです....そしてそれなしでは元のファイルが機能します(末尾のセパレータを残さないことを含む。私は違いがわからない。
カレブ

1
@ gkb0986パスにPATH = / bin:/ foo \ bar:/ usr / binなどのエスケープされたスペースが含まれる場合、このソリューションは依然として失敗します。unix.stackexchange.com/a/124517/106102で
maharvey67

13

@Gillesの回答に基づいて、入力を最小限に抑えるために関数にラップすることができます。

function addToPATH {
  case ":$PATH:" in
    *":$1:"*) :;; # already there
    *) PATH="$1:$PATH";; # or PATH="$PATH:$1"
  esac
}

addToPATH /Applications/AIRSDK_Compiler/bin
addToPATH ~/.local/lib/npm/bin

1
最も実用的な(おそらく高レベルの)回答。
-ijoseph

3

最初の一致のみ$PATHが実行されるため、その後のエントリは処理されません。その$PATHため、環境内のエントリが期待どおりに動作するように、エントリの順序を時々修正する必要があります。

あなたの質問に答えるために:これは起動が遅くなる原因にはなりません。


1
しかし、存在しないコマンドを入力すると時間がかかります。同じフォルダーでコマンドを2回検索します。
バルキ

@balkiコマンドを完了するにはTAB?その場合、完全な定義が次のように見えないかどうかを確認する必要がありますcomplete -c which -a-aパラメーターを削除する必要があります。次のコマンドを発行して確認できますcomplete | grep which
ラジッシュ

同じディレクトリを検索する前に複数回検索しない場合は、依然として問題になる可能性があります。
Random832

-1

PATHにエントリが重複しないようにするために、〜/ .bash_profileと〜/ .bashrcの両方に以下を追加する必要がありました。

PATH=$(echo $(sed 's/:/\n/g' <<< $PATH | sort | uniq) | sed -e 's/\s/':'/g')

主な欠点は、PATHエントリを並べ替えるということですが、私はそれで生きていけると思います。


検索パスの順序は非常に重要です。
スティーブンショー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.