長い$ PATHを編集するより快適な方法は?


35

〜/ .bashrcで、いくつかのディレクトリを$ PATHに追加します。

私の$ PATHは非常に長いため、含まれるディレクトリとその順序を確認するのは少し難しいです。

〜/ .bashrcを次のように変更できることを知っています:

PATH=$PATH:/some/dir
PATH=$PATH:/another/dir:/yet/another
PATH=$PATH:/and/another
...

読みやすくなります。しかし、ここ数年の間に、Bashは長いPATHを簡単に指定できる構文を取得しているかどうか疑問に思っていました。例えば、私は次のような構文について空想しています:

PATH=:((
  /some/dir
  /another/dir
  /yet/another
  /and/another
  ...
))

そのような構文が無効であること知っています。簡単なものがあるかどうか疑問に思っていました。ある?


経由でパスを設定する従来のチュートリアルは、PATH=foo:$PATH毎回成長を続けておりsource ~/.bashrc、それexec bash以降も役に立たないため、間違っているよう$PATHですexport
林果皞8:15

回答:


25

パスを変数に追加または追加するために、一連の便利な関数を使用します。関数は、「pathfuncs」と呼ばれるcontribファイルでBashの配布tarballに入っています。

  • add_pathは、エントリをPATH変数の最後に追加します
  • pre_pathは、PATH変数の先頭にエントリを追加します
  • del_pathは、どこにいてもPATH変数からエントリを削除します

2番目の引数として変数を指定すると、PATHの代わりにその変数が使用されます。

便宜上、ここにあります:

# is $1 missing from $2 (or PATH) ?
no_path() {
    eval "case :\$${2-PATH}: in *:$1:*) return 1;; *) return 0;; esac"
}
# if $1 exists and is not in path, append it
add_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1"
}
# if $1 exists and is not in path, prepend it
pre_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}"
}
# if $1 is in path, remove it
del_path () {
  no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: |
    sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"`
}

これらをbashスタートアップファイルに追加する場合、次のようにPATHに追加できます。

pre_path $HOME/bin
add_path /sbin
add_path /usr/sbin

または、別の変数を指定します。

pre_path $HOME/man MANPATH
pre_path $HOME/share/man MANPATH
add_path /usr/local/man MANPATH
add_path /usr/share/man MANPATH

rcファイルでこのメソッドを使用して、pre_pathsを最初に、add_pathsを2番目に配置します。すべてのパスの変更が一目で理解しやすくなります。もう1つの利点は、行が十分に短いため、必要に応じて行の末尾にコメントを追加できることです。

また、これらは関数であるadd_path $(pwd)ため、現在のディレクトリをパスに追加するなどのコマンドラインから対話的に使用できます。


ありがとう。あなたのコードをチェックしましたが、動作します。驚いたことに、del_pathの使用も見つけました(状況によっては "。"が私のPATHに忍び込んでいdel_path .ます。
ニッコロM.

こんにちは。このpathfuncsをbashrcスクリプトからソース(インクルード)することは可能ですか、それともそこにコピー/ペーストする必要がありますか?
クリスティアーノ

@Cristianoどちらでも動作します。本当にあなた次第です。
ヒトデ

11

OK、次の解決策を見つけました。エレガントだと思います(シェル構文に関する限り)。Bashの配列構文と、要素を結合するためのきちんとした方法を使用します。

paths=(
  /some/dir
  /another/dir
  '/another/dir with spaces in it'
  /yet/another
  /and/another
  /end
)
paths_joined=$( IFS=: ; echo "${paths[*]}" )

PATH=$paths_joined:$PATH

アラート!

この解決策には問題があることがわかります。@ terdonや@Starfishの解決策とは異なり、最初にパスが既にPATHにあるかどうかをチェックしません。したがって、このコードを〜/ .bashrc(〜/ .profileではなく)に配置したいので、重複したパスがPATHに忍び込んでしまいます。したがって、このソリューションを使用しないでください(〜/ .profileに入れない限り(または、Bash固有の構文があるため、〜/ .bash_profile)。)


1
非常に素晴らしい。答えを受け入れて、他の人がここに来て解決策を見つけてくれないように、あなたはすでにそれを見つけましたか?ありがとう
基本的な

パスの重複は実際には問題ではありません。PATH実際にパフォーマンスの問題を引き起こすのに十分なディレクトリを追加することはほとんどありません(特にシェルは成功したルックアップをキャッシュするため)。
-chepner

5

私は私の以下で関数を使用します~/.bashrc。古いラボのシステム管理者から得たものですが、彼が書いたとは思いません。これらの行を~/.profileorに追加するだけ~/.bashrcです:

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

これにはさまざまな利点があります。

  • 新しいディレクトリを追加するの$PATHは簡単ですpathmunge /foo/bar
  • 重複エントリを回避します。
  • 新しいエントリをの先頭(pathmunge /foo/barまたは末尾(pathmunge /foo/bar後))に追加するかどうかを選択できます$PATH

シェルの初期化ファイルには次のようなものが含まれます。

pathmunge /some/dir
pathmunge /another/dir
pathmunge '/another/dir with spaces in it'
pathmunge /yet/another
pathmunge /and/another
pathmunge /end

ありがとう。しかし、@ Starfishが生成されないため、@ Starfishのソリューションを選択しますgrep
ニッコロM.

2
にゃん 問題ありません。どちらを選んでもかまいません。ただし、ヒトデのアプローチには注意しevalてください。間違った引数で実行すると、重大な損害を引き起こす可能性があるため、任意のコードが実行されます。
テルドン

より高速な関数が外部コマンドなしでそれを行うためにはredhatに存在することに注意してgrep、参照bugzilla.redhat.com/show_bug.cgi?id=544652#c7
林果皞

4

〜/ .bashrcで、いくつかのディレクトリを$ PATHに追加します。

Cygwinでは次を使用します。他のバージョンのbashでも動作するはずです。unset PATH現在のビルドを削除できますPATH(これを行う場合は、:セパレーターを正しく追加する方法を理解する必要があります)。

注意:

  • 私はかつて関数にこの機能を持っていましたbashが、ディスクのクラッシュ後にそれを失いました。

私の.bash_profile

# Build up the path using the directories in ~/.path_elements
unset PATH
while read line; do 
  PATH="${PATH}$line"; 
done < ~/.path_elements

...

# Add current directory to path
export PATH=".:${PATH}"

~/.path_elements

/home/DavidPostill/bin:
/usr/local/bin:
/usr/bin:
/c/Windows/system32:
/c/Windows

ありがとう。あなたの答えは私に同種のソリューションに取り組むきっかけになりました。(私の好みでは、パスを別のファイルに保存するのは面倒です。)
ニッコロM.

1

これを.bashrcで使用します(また、bashの代わりに使用可能な場合は通常zshを使用するため、.zshrcも使用します)。確かに、手動でディレクトリを追加する必要がありますが、利点は、更新するときに新しいサーバーにコピーし続けることができ、そこに存在しないディレクトリで作成された新しいサーバーのPATHを心配しないことです。

##
##パス
##
##次のようなディレクトリでパスを破壊する代わりに
##このサーバーには適切ではありません。追加するものについてインテリジェントになるようにしてください
##
PATH = / usr / local / sbin:/ usr / local / bin:/ usr / sbin:/ usr / bin:/ sbin:/ bin
[-d / cs / sbin] && PATH = / cs / sbin:$ PATH
[-d / cs / bin] && PATH = / cs / bin:$ PATH
[-d / usr / ucb] && PATH = $ PATH:/ usr / ucb
[-d / usr / ccs / bin] && PATH = $ PATH:/ usr / ccs / bin
[-d / usr / local / ssl / bin] && PATH = $ PATH:/ usr / local / ssl / bin
[-d / usr / krb5 / bin] && PATH = $ PATH:/ usr / krb5 / bin
[-d / usr / krb5 / sbin] && PATH = $ PATH:/ usr / krb5 / sbin
[-d / usr / kerberos / sbin] && PATH = $ PATH:/ usr / kerberos / sbin
[-d / usr / kerberos / bin] && PATH = $ PATH:/ usr / kerberos / bin
[-d /cs/local/jdk1.5.0/bin] && PATH = $ PATH:/cs/local/jdk1.5.0/bin
[-d /usr/java/jre1.5.0_02/bin] && PATH = $ PATH:/usr/java/jre1.5.0_02/man
[-d /usr/java1.2/bin] && PATH = $ PATH:/usr/java1.2/bin
[-d /cs/local/perl5.8.0/bin] && PATH = $ PATH:/cs/local/perl5.8.0/bin
[-d / usr / perl5 / bin] && PATH = $ PATH:/ usr / perl5 / bin
[-d / usr / X11R6 / bin] && PATH = $ PATH:/ usr / X11R6 / bin
[-d / etc / X11] && PATH = $ PATH:/ etc / X11
[-d / opt / sfw / bin] && PATH = $ PATH:/ opt / sfw / bin
[-d / usr / local / apache / bin] && PATH = $ PATH:/ usr / local / apache / bin
[-d / usr / apache / bin] && PATH = $ PATH:/ usr / apache / bin
[-d / cs / admin / bin] && PATH = $ PATH:/ cs / admin / bin
[-d / usr / openwin / bin] && PATH = $ PATH:/ usr / openwin / bin
[-d / usr / xpg4 / bin] && PATH = $ PATH:/ usr / xpg4 / bin
[-d / usr / dt / bin] && PATH = $ PATH:/ usr / dt / bin

私は私のMANPATHに対して同じことをします:

##
##マンパス
##
##可能性のあるディレクトリでMANPATHを上書きする代わりに
##このサーバーには適切ではありません。追加するものについてインテリジェントになるようにしてください
##
MANPATH = / usr / local / man
[-d / usr / share / man] && MANPATH = $ MANPATH:/ usr / share / man
[-d / usr / local / share / man] && MANPATH = $ MANPATH:/ usr / local / share / man
[-d / usr / man] && MANPATH = $ MANPATH:/ usr / man
[-d / cs / man] && MANPATH = $ MANPATH:/ cs / man
[-d / usr / krb5 / man] && MANPATH = $ MANPATH:/ usr / krb5 / man
[-d / usr / kerberos / man] && MANPATH = $ MANPATH:/ usr / kerberos / man
[-d / usr / local / ssl / man] && MANPATH = $ MANPATH:/ usr / local / ssl / man
[-d /cs/local/jdk1.5.0/man] && MANPATH = $ MANPATH:/cs/local/jdk1.5.0/man
[-d /usr/java/jre1.5.0_02/man] && MANPATH = $ MANPATH:/usr/java/jre1.5.0_02/man
[-d /usr/java1.2/man] && MANPATH = $ MANPATH:/usr/java1.2/man
[-d / usr / X11R6 / man] && MANPATH = $ MANPATH:/ usr / X11R6 / man
[-d / usr / local / apache / man] && MANPATH = $ MANPATH:/ usr / local / apache / man
[-d / usr / local / mysql / man] && MANPATH = $ MANPATH:/ usr / local / mysql / man
[-d /cs/local/perl5.8.0/man] && MANPATH = $ MANPATH:/cs/local/perl5.8.0/man
[-d / usr / perl5 / man] && MANPATH = $ MANPATH:/ usr / perl5 / man
[-d / usr / local / perl / man] && MANPATH = $ MANPATH:/ usr / local / perl / man
[-d /usr/local/perl5.8.0/man] && MANPATH = $ MANPATH:/usr/local/perl5.8.0/man
[-d / usr / openwin / man] && MANPATH = $ MANPATH:/ usr / openwin / man

PATHに存在しないディレクトリを追加することを恐れずに、異なる環境のシステムにコピーできる単一のファイルがあることに加えて、このアプローチには、ディレクトリをPATHに表示する順序を指定できるという利点もあります。各定義の最初の行はPATH変数を完全に再定義しているため、.bashrcを更新し、編集後にシェルを更新して、重複したエントリを追加せずにシェルを更新できます(これは、「 $ PATH = $ PATH:/ new / dir "。これにより、希望する順序でクリーンコピーを取得できます。


1
代替案の提案: d="/usr/share/man" ; [ -d "$d" ] && MANPATH="$MANPATH:${d}"短くなり、新しいディレクトリを追加するのが簡単になります(行をコピーして最初の「d = ....」部分を編集するだけです)。ただし、PATHの場合は、PATHに非常に多くのディレクトリが存在することになります。これは常に良いとは限りません(「foo」コマンドがあまり知られていないパスの1つに存在し、通常のユーザーが何を期待するか?)
オリビエデュラック

OPは、パスを追加するより簡潔な方法を求めました。これは、彼らがすでに回避しようとしていたものよりもはるかに冗長でエラーを起こしやすいです。
underscore_d

-1

簡単な方法があります!読むシェル関数とパス変数でのLinuxのジャーナル2000年3月1日により、スティーブンCollyer

これらの関数を使用すると、bash環境で新しいデータ型(コロン区切りリスト)を使用できます。PATHに加えて、これらを使用してLOCATE_PATH、MANPATHなどを調整し、bashプログラミングの一般的なデータ型として使用します。PATHの設定方法は次のとおりです(関数を使用):

# Add my bin directory to $PATH at the beginning, so it overrides 
addpath -f -p PATH $HOME/bin

# For Raspberry Pi development (add at end)
addpath -b -p PATH ${HOME}/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

# remove nonexistent directories from PATH
delpath -n -p PATH

# ensure PATH contains unique entries
uniqpath -p PATH

Linux Journalリンクは「壊れた」と呼ばれるため、http: //pastebin.ubuntu.com/13299528/の.sharファイルにBash Path Functionsを配置しました。


3
これらの機能は何ですか?OPはそれらをどのように使用しますか?おそらくあなたの答えの壊れたリンクで説明されているので、私たちは常に答えを自己完結させたいと思っています。実際の関数を編集して回答に含めてください。
テルドン

@terdon:リンクは私のために機能します。ペーストビンに.sharファイルを置きます。ここには1K行を投稿しません。
ワルチネーター

おっと、今も私のために働いています。コメントを残したときはそうではなかった。とにかく、私のコメントの要点は、回答内の外部リソースへのリンクを避けようとすることでした。ここで情報を更新、編集でき、リンク腐敗の影響を受けないようにする必要があります
テルドン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.