現在の作業ディレクトリに応じて、$PATH
環境変数を変更したいと思います。
私が/foo/bar/baz
にいて、ディレクトリ/foo/node_modules/.bin
と/foo/bar/baz/node_modules/.bin
があるとします。可能なすべての./node_modules/.bin
を$PATH
に再帰的に追加したいと思います。
しかし、cd
を別のディレクトリ(/foo/bar
など)に移動するときは、元のクリーンな$PATH
を復元してから、./node_modules/.bin
を再帰的に探し始めます。再び。
(npmの課題追跡システムからの自分の質問を解決したい: ローカルにインストールされたパッケージもPATHに追加できますか? )
注:私はMacを使用していますが、一般的な解決策に興味があります。
私があなたを正しく理解している場合は、ディレクトリ"$X/node_modules/.bin"
を追加します。ここで、$X
は$PWD
またはその祖先のいずれかです。
この投稿の最後にあるスクリプトは、必要な動作を提供するはずです。あなたはそれを望むすべてのセッションでそれを調達する必要があります。ファイルにaugment_path.sh
という名前を付ける場合は、この行を.bashrc
に追加するだけで十分です。
source augment_path.sh
Garyjohnは基本的なアプローチを正しく持っていると思いますが、彼はすべての祖先ではなく、すべての子孫を検索しています。
$Prompt_COMMAND
変数を使用すると、プロンプトが表示されるたびに実行されるコマンドを指定できます。元の$Prompt_COMMAND_OLD
を復元できるように$Prompt_COMMAND
変数を追加しました
おそらく必要ではありませんが、適切な形式にするために、$LAST_WD
変数を追加し、ディレクトリが変更されていないときにパスが再計算されないようにテストします。必要に応じて、LAST_WD
を含む3行すべてを削除できます。
augment_path
関数は$PWD
から上にスキャンし、各祖先のターゲットディレクトリを探し、見つかったものをパスに追加します。
それらは順番にパスに配置されるため、競合がある場合は、そのような最も深いディレクトリが優先されます。これが望ましい動作だと思います。そうでない場合は、変更します
PATH_ADDITION="$PATH_ADDITION:$resolved_target"
に
PATH_ADDITION="$resolved_target:$PATH_ADDITION"
ただし、これらのディレクトリはすべて、パスの残りの部分よりも優先されます。パスの残りの部分を優先する場合は、次を変更します。
PATH="$PATH_ADDITION:$RAW_PATH"
に
PATH="$RAW_PATH:$PATH_ADDITION"
RAW_PATH="$PATH"
LAST_WD=`pwd`
augment_path() {
target="node_modules/.bin"
if [ "$PWD" = "$LAST_WD" ]; then return 0; fi;
PATH_ADDITION=""
scandir="$PWD"
until [ "$scandir" = "" ]; do
resolved_target="$scandir"/"$target"
if [ -d "$resolved_target" ]; then
PATH_ADDITION="$PATH_ADDITION:$resolved_target"
fi
scandir="${scandir%/*}"
done
PATH="$PATH_ADDITION:$RAW_PATH"
LAST_WD=`pwd`
}
Prompt_COMMAND_OLD="${Prompt_COMMAND%; augment_path}"
Prompt_COMMAND="$Prompt_COMMAND_OLD; augment_path"
以下を~/.bashrc
に入れるとあなたが望むことをするだろうと思います。
Bash環境変数Prompt_COMMAND
が何らかのコマンドに設定されている場合、bashがプライマリプロンプトを表示する前にそのコマンドが実行されます。
以下のコードでは、Prompt_COMMAND
が関数の名前doit
に設定されています。この関数は、現在の作業ディレクトリが変更されたかどうかを確認し、変更された場合は、最初にPATH
を元の値に設定してから、node_modules/.bin
という名前のサブディレクトリの存在を確認します。そのサブディレクトリが存在する場合、関数はそのサブディレクトリの名前とその下のすべてのサブディレクトリをPATH
に追加します。
orig_path="$PATH"
prev_pwd=""
doit() {
if [ "$PWD" != "$prev_pwd" ]; then
PATH="$orig_path"
if [ -d "node_modules/.bin" ]; then
PATH="$PATH$(find $PWD/node_modules/.bin -type d -printf ':%p')"
# For POSIX compatibility (macOS or other), use:
# PATH="$PATH$(find $PWD/node_modules/.bin -type d -exec echo -n :{} \;)"
fi
prev_pwd="$PWD"
fi
}
Prompt_COMMAND=doit
Bashを使用できます Prompt_COMMAND
:
Prompt_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin'
そのコマンドは、プロンプトが表示されるたびに実行されます。したがって、コマンドが終了するたびに、PATH
変数が変更されます。追加のディレクトリが最後に追加されます。
ディレクトリがない場合./node_modules/.bin
現在の作業ディレクトリでは、とにかくパスが追加されます。しかし、それは問題ではありません。トラフでは検索されません(存在しないため)。
デモを参照してください。
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ Prompt_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin'
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/node_modules/.bin
$ cd test
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/test/node_modules/.bin
$ cd /etc/
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/node_modules/.bin