Tôi hơi ngạc nhiên khi chưa có ai đề cập đến vấn đề này, nhưng bạn có thể sử dụng readlink -f
để chuyển đổi các đường dẫn tương đối thành các đường dẫn tuyệt đối và thêm chúng vào PATH như vậy.
Ví dụ: để cải thiện câu trả lời của Guillaume Perrault-Archambault,
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
PATH="${PATH:+"$PATH:"}$ARG"
fi
done
}
trở thành
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. Những điều cơ bản - Điều này có ích gì?
Các readlink -f
lệnh sẽ (trong số những thứ khác) chuyển đổi một đường dẫn tương đối đến một đường dẫn tuyệt đối. Điều này cho phép bạn làm một cái gì đó như
$ cd / đường dẫn / đến / của tôi / bin / dir
$ pathappend .
$ echo "$ PATH"
<your_old_path> : / path / to / my / bin / dir
2. Tại sao chúng ta thử nghiệm để được ở trong hai lần?
Vâng, hãy xem xét ví dụ trên. Nếu người dùng nói
từ thư mục lần thứ hai,
sẽ có . Tất nhiên, sẽ không có mặt trong . Nhưng sau đó sẽ được thiết lập để
(đường dẫn tuyệt đối tương đương ), mà là đã có trong . Vì vậy, chúng ta cần tránh thêm vào lần thứ hai.pathappend .
/path/to/my/bin/dir
ARG
.
.
PATH
ARGA
/path/to/my/bin/dir
.
PATH
/path/to/my/bin/dir
PATH
Có lẽ quan trọng hơn, mục đích chính của readlink
, như tên của nó ngụ ý, để xem xét một liên kết tượng trưng và đọc tên đường dẫn mà nó chứa (nghĩa là trỏ đến). Ví dụ:
$ 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
Bây giờ, nếu bạn nói pathappend /usr/lib/perl/5.14
, và bạn đã có /usr/lib/perl/5.14
trong ĐƯỜNG của bạn, tốt, điều đó tốt; chúng ta có thể để nó như vậy Nhưng, nếu /usr/lib/perl/5.14
chưa có trong PATH của bạn, chúng tôi gọi readlink
và get ARGA
= /usr/lib/perl/5.14.2
, và sau đó chúng tôi thêm nó vào PATH
. Nhưng hãy đợi một phút - nếu bạn đã nói pathappend /usr/lib/perl/5.14
, thì bạn đã có /usr/lib/perl/5.14.2
trong ĐƯỜNG của bạn, và, một lần nữa, chúng ta cần kiểm tra điều đó để tránh thêm nó vào PATH
lần thứ hai.
3. Thỏa thuận với if ARGA=$(readlink -f "$ARG")
cái gì?
Trong trường hợp không rõ ràng, dòng này kiểm tra xem liệu readlink
thành công. Đây chỉ là tốt, thực hành lập trình phòng thủ. Nếu chúng ta sẽ sử dụng đầu ra từ lệnh m
như một phần của lệnh n (trong đó m < n ), thì nên kiểm tra xem lệnh m có bị lỗi hay không và xử lý theo cách nào đó. Tôi không nghĩ rằng nó có khả năng readlink
sẽ thất bại - nhưng, như đã thảo luận trong Cách lấy đường dẫn tuyệt đối của một tệp tùy ý từ OS X
và các nơi khác, readlink
là một phát minh GNU. Nó không được chỉ định trong POSIX, vì vậy tính khả dụng của nó trong Mac OS, Solaris và các Unix không phải Linux khác là đáng nghi ngờ. (Trên thực tế, tôi vừa đọc một bình luận nói rằngreadlink -f
dường như không hoạt động trên Mac OS X 10.11.6, nhưng realpath
hoạt động vượt trội . Vì vậy, nếu bạn đang sử dụng hệ thống không có readlink
hoặc readlink -f
không hoạt động, bạn có thể sửa đổi điều này script để sử dụng realpath
.) Bằng cách cài đặt một mạng lưới an toàn, chúng tôi làm cho mã của chúng tôi dễ mang theo hơn.
Tất nhiên, nếu bạn trên một hệ thống không có readlink
(hoặc realpath
), bạn sẽ không muốn làm .pathappend .
Bài -d
kiểm tra thứ hai ( [ -d "$ARGA" ]
) thực sự có lẽ không cần thiết. Tôi không thể nghĩ ra bất kỳ kịch bản nào $ARG
là thư mục và readlink
thành công, nhưng $ARGA
không phải là thư mục. Tôi chỉ sao chép và dán if
câu lệnh đầu tiên để tạo câu lệnh thứ ba, và tôi rời khỏi -d
bài kiểm tra ở đó vì sự lười biếng.
4. Có ý kiến nào khác không?
Vâng. Giống như nhiều câu trả lời khác ở đây, câu trả lời này kiểm tra xem mỗi đối số có phải là một thư mục hay không, xử lý nó nếu có và bỏ qua nó nếu không. Điều này có thể (hoặc có thể không) là đầy đủ nếu bạn pathappend
chỉ sử dụng trong .
các tập tin của EDR (như .bash_profile
và .bashrc
) và các tập lệnh khác. Nhưng, như câu trả lời này cho thấy (ở trên), việc sử dụng nó một cách tương tác là hoàn toàn khả thi. Bạn sẽ rất bối rối nếu bạn làm
$ pathappend /usr/local/nysql/bin
$ mysql
-bash: mysql: command not found
Bạn có nhận thấy rằng tôi đã nói nysql
trong pathappend
lệnh, hơn là mysql
? Và điều đó pathappend
không nói lên điều gì; Nó chỉ âm thầm bỏ qua lập luận không chính xác?
Như tôi đã nói ở trên, đó là cách thực hành tốt để xử lý lỗi. Đây là một ví dụ:
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
}