まだ誰もこれに言及していないことに少し驚いていますがreadlink -f
、相対パスを絶対パスに変換し、PATHに追加するために使用できます。
たとえば、ギヨームペローアルシャンボーの答えを改善するには、
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
PATH="${PATH:+"$PATH:"}$ARG"
fi
done
}
になる
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]
then
if ARGA=$(readlink -f "$ARG") #notice me
then
if [ -d "$ARGA" ] && [[ ":$PATH:" != *":$ARGA:"* ]]
then
PATH="${PATH:+"$PATH:"}$ARGA"
fi
else
PATH="${PATH:+"$PATH:"}$ARG"
fi
fi
done
}
1.基本—これはどのような利点がありますか?
このreadlink -f
コマンドは(とりわけ)相対パスを絶対パスに変換します。これにより、次のようなことができます
$ cd / path / to / my / bin / dir
$ pathappend 。
$ echo "$ PATH"
<your_old_path>:/ path / to / my / bin / dir
2. PATHに2回入ることをテストする理由
さて、上記の例を考えてみましょう。ユーザーがディレクトリ
からもう一度言うと、に
なります。もちろん、には存在しません。ただし、は
(に相当する絶対パス)に設定されます。これは既にです。だから我々は、追加することを避けるために必要に二度目。pathappend .
/path/to/my/bin/dir
ARG
.
.
PATH
ARGA
/path/to/my/bin/dir
.
PATH
/path/to/my/bin/dir
PATH
おそらくより重要なことは、その主な目的readlink
は、その名前が示すように、シンボリックリンクを見て、それに含まれる(つまり指す)パス名を読み取ることです。例えば:
$ ls -ld /usr/lib/perl/5.14
-rwxrwxrwx 1 root root Sep 3 2015 /usr/lib/perl/5.14 -> 5.14.2
$ readlink /usr/lib/perl/5.14
5.14.2
$ readlink -f /usr/lib/perl/5.14
/usr/lib/perl/5.14.2
さて、あなたが言うならpathappend /usr/lib/perl/5.14
、あなたはすでに/usr/lib/perl/5.14
あなたのPATHにあります、まあ、それは大丈夫です; そのままにしておくことができます。しかし、もし/usr/lib/perl/5.14
あなたのPATHにない、我々は呼び出すreadlink
とget ARGA
=を/usr/lib/perl/5.14.2
、その後、我々は追加していることにPATH
。しかし、ちょっと待って-あなたがあれば、既に述べpathappend /usr/lib/perl/5.14
、その後、あなたはすでに持っている/usr/lib/perl/5.14.2
もう一度、あなたのPATHに、そして、我々はそれを追加することを避けるためにそれをチェックする必要がPATH
二度目。
3.取引とは何if ARGA=$(readlink -f "$ARG")
ですか?
不明な場合、この行はreadlink
成功するかどうかをテストします。これは、優れた防御的なプログラミングの実践です。コマンドmの出力をコマンド nの一部
として使用する 場合(m < n)、コマンドmが失敗したかどうかを確認し、何らかの方法で処理するのが賢明 です。readlink
失敗する可能性は低いと思いますが、OS X
などから任意のファイルの絶対パスを取得する方法で説明したようにreadlink
、GNUの発明です。POSIXでは指定されていないため、Mac OS、Solaris、およびその他のLinux以外のUnixでの可用性は疑わしいです。(実際に、私はちょうど読んコメント「と言いますreadlink -f
Mac OS X 10.11.6では動作しないように見えrealpath
ますが、すぐに動作します。」ですので、システムがないreadlink
、またはreadlink -f
動作しない場所では、これを変更できる可能性があります使用するスクリプトrealpath
。)セーフティネットをインストールすることで、コードの移植性をいくらか高めます。
もちろん、持っていないreadlink
(または realpath
)システムを使用している場合は、したくないでしょう。pathappend .
2番目の-d
テスト([ -d "$ARGA" ]
)は、おそらく不要です。$ARG
ディレクトリでreadlink
成功する シナリオは考えられませんが、ディレクトリで$ARGA
はありません。私は最初のコピーと貼り付け、if
三番目を作成するためのステートメントを、と私は左の -d
怠惰のうち、そこにテストを。
4.他にコメントはありますか?
うん。ここでの他の多くの回答と同様に、これは各引数がディレクトリであるかどうかをテストし、ある場合は処理し、ない場合は無視します。pathappend
「.
」ファイル(.bash_profile
やなど.bashrc
)やその他のスクリプトでのみ使用している場合、これは適切な場合もあれば、そうでない場合もあります。しかし、この回答が示したように(上記)、インタラクティブに使用することは完全に実行可能です。あなたがする場合、あなたは非常に困惑します
$ pathappend /usr/local/nysql/bin
$ mysql
-bash: mysql: command not found
コマンドではなくnysql
、私が言ったことに気づきましたか?そして、それは何も言わなかった。間違った引数を静かに無視しただけですか?pathappend
mysql
pathappend
上で言ったように、エラーを処理するのは良い習慣です。次に例を示します。
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ]
then
if [[ ":$PATH:" != *":$ARG:"* ]]
then
if ARGA=$(readlink -f "$ARG") #notice me
then
if [[ ":$PATH:" != *":$ARGA:"* ]]
then
PATH="${PATH:+"$PATH:"}$ARGA"
fi
else
PATH="${PATH:+"$PATH:"}$ARG"
fi
fi
else
printf "Error: %s is not a directory.\n" "$ARG" >&2
fi
done
}