Saya agak terkejut bahwa belum ada yang menyebutkan ini, tetapi Anda dapat menggunakan readlink -f
untuk mengubah jalur relatif ke jalur absolut, dan menambahkannya ke PATH.
Misalnya, untuk meningkatkan jawaban Guillaume Perrault-Archambault,
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
PATH="${PATH:+"$PATH:"}$ARG"
fi
done
}
menjadi
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. Dasar-Dasar - Apa Manfaat Hal Ini?
The readlink -f
perintah akan (antara lain) mengkonversi path relatif ke path absolut. Ini memungkinkan Anda melakukan sesuatu seperti
$ cd / path / ke / my / bin / dir
$ pathappend .
$ echo "$ PATH"
<your_old_path> : / path / ke / my / bin / dir
2. Mengapa Kami Menguji Berada di PATH Dua Kali?
Nah, perhatikan contoh di atas. Jika pengguna mengatakan
dari direktori untuk kedua kalinya,
akan . Tentu saja, tidak akan hadir di . Tapi kemudian akan ditetapkan ke
(setara dengan path absolut dari ), yang merupakan sudah . Jadi kita perlu menghindari menambahkan untuk yang kedua kalinya.pathappend .
/path/to/my/bin/dir
ARG
.
.
PATH
ARGA
/path/to/my/bin/dir
.
PATH
/path/to/my/bin/dir
PATH
Mungkin yang lebih penting, tujuan utama readlink
adalah, seperti namanya, untuk melihat tautan simbolis dan membaca pathname yang dikandungnya (yaitu, menunjuk ke). Sebagai contoh:
$ 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
Sekarang, jika Anda berkata pathappend /usr/lib/perl/5.14
, dan Anda sudah memiliki /usr/lib/perl/5.14
di PATH Anda, baik, itu baik-baik saja; kita bisa membiarkannya apa adanya. Tapi, jika /usr/lib/perl/5.14
tidak sudah di PATH Anda, kita sebut readlink
dan ARGA
= /usr/lib/perl/5.14.2
, dan kemudian kita menambahkan bahwa untuk PATH
. Tapi tunggu sebentar - jika Anda sudah mengatakan pathappend /usr/lib/perl/5.14
, maka Anda sudah memiliki /usr/lib/perl/5.14.2
dalam PATH Anda, dan, sekali lagi, kita perlu memeriksa itu untuk menghindari menambahkannya ke PATH
yang kedua kalinya.
3. Apa Kesepakatannya if ARGA=$(readlink -f "$ARG")
?
Jika tidak jelas, baris ini menguji apakah readlink
berhasil. Ini hanya praktik pemrograman defensif yang bagus. Jika kita akan menggunakan output dari perintah m
sebagai bagian dari perintah n (di mana m < n ), lebih baik untuk memeriksa apakah perintah m gagal dan menanganinya dengan cara tertentu. Saya tidak berpikir kemungkinan itu readlink
akan gagal - tetapi, seperti yang dibahas dalam Cara mengambil jalur absolut file sewenang-wenang dari OS X
dan di tempat lain, readlink
adalah penemuan GNU. Ini tidak ditentukan dalam POSIX, jadi ketersediaannya di Mac OS, Solaris, dan Unix non-Linux lainnya dipertanyakan. (Bahkan, saya baru saja membaca komentar yang mengatakan "readlink -f
tampaknya tidak berfungsi di Mac OS X 10.11.6, tetapi realpath
bekerja di luar kotak. ”Jadi, jika Anda menggunakan sistem yang tidak memiliki readlink
, atau di mana readlink -f
tidak berfungsi, Anda mungkin dapat memodifikasi ini skrip untuk digunakan realpath
.) Dengan memasang jaring pengaman, kami membuat kode kami agak lebih portabel.
Tentu saja, jika Anda menggunakan sistem yang tidak memiliki readlink
(atau realpath
), Anda tidak akan mau melakukannya .pathappend .
-d
Tes kedua ( [ -d "$ARGA" ]
) mungkin benar-benar tidak perlu. Saya tidak bisa memikirkan skenario di mana $ARG
direktori dan readlink
berhasil, tetapi $ARGA
bukan direktori. Saya hanya menyalin dan menempelkan if
pernyataan pertama untuk membuat yang ketiga, dan saya meninggalkan -d
tes karena malas.
4. Ada Komentar Lain?
Ya. Seperti banyak jawaban lain di sini, yang ini menguji apakah setiap argumen adalah direktori, memprosesnya jika ada, dan mengabaikannya jika tidak. Ini mungkin (atau mungkin tidak) memadai jika Anda pathappend
hanya menggunakan .
file " " (seperti .bash_profile
dan .bashrc
) dan skrip lainnya. Tetapi, seperti yang ditunjukkan oleh jawaban ini (di atas), sangat layak untuk menggunakannya secara interaktif. Anda akan sangat bingung jika melakukannya
$ pathappend /usr/local/nysql/bin
$ mysql
-bash: mysql: command not found
Apakah Anda memperhatikan bahwa saya mengatakan nysql
dalam pathappend
perintah, bukan mysql
? Dan itu pathappend
tidak mengatakan apa-apa; hanya diam-diam mengabaikan argumen yang salah?
Seperti yang saya katakan di atas, praktik yang baik untuk menangani kesalahan. Ini sebuah contoh:
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
}