web-dev-qa-db-ja.com

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

〜/ .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
  ...
))

I knowこのような構文は無効です。こんなに簡単なことはあるのかと思っていました。ある?

35
Niccolo M.

変数へのパスの先頭または末尾に一連の便利な関数を使用しています。関数は、「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番目に配置しています。これにより、パスの変更がすべて一目でわかりやすくなります。別の利点は、行が十分に短いため、必要に応じて行の末尾にコメントを追加できることです。

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

25
Starfish

OK、次の解決策を見つけました。これはエレガントだと思います(シェル構文に関する限り)。これはBashの配列構文と neat way を使用して要素を結合します。

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の解決策とは異なり、最初にパスがすでに存在するかどうかをチェックしません道。したがって、このコードを〜/ .bashrc(〜/ .profileではなく)に配置したいので、重複したパスがPATHに侵入します。したがって、このソリューションは使用しないでください(〜/ .profile(またはBash固有の構文があるため、より良いのは〜/ .bash_profile)に配置する場合を除きます)。

11
Niccolo M.

以下の関数を~/.bashrcで使用しています。私の古いラボのシステム管理者から入手したものですが、彼がそれらを書いたとは思いません。これらの行を~/.profileまたは~/.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
5
terdon

〜/ .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
4
DavidPostill

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

 ## 
 ## PATH 
 ## 
 ##次の場合に適切でない可能性のあるディレクトリを使用して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/bi n] && 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を次のディレクトリで適切に壊すのではなく、
 ##は適切ではありませんこのサーバーでは、追加するものについてインテリジェントに考えてください
 ## 
 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/Ja va1.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
Brian Snook