Tôi đang tự hỏi nơi một đường dẫn mới phải được thêm vào biến môi trường PATH
. Tôi biết điều này có thể được thực hiện bằng cách chỉnh sửa .bashrc
(ví dụ), nhưng không rõ làm thế nào để làm điều này.
Cách này:
export PATH=~/opt/bin:$PATH
hay cái này
export PATH=$PATH:~/opt/bin
PATH=$PATH:~/opt/bin
hoặc là
PATH=~/opt/bin:$PATH
tùy thuộc vào việc bạn muốn thêm ~/opt/bin
ở cuối (được tìm kiếm sau tất cả các thư mục khác, trong trường hợp có một chương trình có cùng tên trong nhiều thư mục) hoặc ở đầu (được tìm kiếm trước tất cả các thư mục khác).
Bạn có thể thêm nhiều mục cùng một lúc. PATH=$PATH:~/opt/bin:~/opt/node/bin
hoặc các biến thể của công việc đặt hàng tốt. Đừng đặt export
ở đầu dòng vì nó có các biến chứng bổ sung (xem bên dưới phần Ghi chú trên vỏ ngoài các bash khác).
Nếu PATH
của bạn được xây dựng bởi nhiều thành phần khác nhau, bạn có thể sẽ có các mục trùng lặp. Xem Cách thêm đường dẫn thư mục chính được phát hiện bởi lệnh Unix nào? và Xóa các mục nhập $ PATH trùng lặp bằng lệnh awk để tránh thêm trùng lặp hoặc xóa chúng.
Một số bản phân phối tự động đặt ~/bin
trong PATH của bạn nếu nó tồn tại, nhân tiện.
Đặt dòng để sửa đổi PATH
in ~/.profile
hoặc trong ~/.bash_profile
nếu đó là những gì bạn có.
Lưu ý rằng ~/.bash_rc
không được đọc bởi bất kỳ chương trình nào và ~/.bashrc
là tệp cấu hình của các phiên bản tương tác của bash. Bạn không nên xác định các biến môi trường trong ~/.bashrc
. Vị trí thích hợp để xác định các biến môi trường, chẳng hạn như PATH
là ~/.profile
(hoặc là ~/.bash_profile
nếu bạn không quan tâm đến các vỏ khác ngoài bash). Xem Sự khác biệt giữa chúng và tôi nên sử dụng cái nào?
Đừng đặt nó vào /etc/environment
hoặc là ~/.pam_environment
: đây không phải là các tệp Shell, bạn không thể sử dụng các thay thế như $PATH
trong đó. Trong các tệp này, bạn chỉ có thể ghi đè một biến, không thêm vào nó.
Bạn không cần export
nếu biến đã có trong môi trường: mọi thay đổi của giá trị của biến được phản ánh trong môi trường.¹ PATH
luôn luôn tồn tại trong môi trường; tất cả các hệ thống unix thiết lập nó rất sớm (thường là trong quá trình đầu tiên, trên thực tế).
Tại thời điểm đăng nhập, bạn có thể dựa vào PATH
đang ở trong môi trường và đã chứa một số thư mục hệ thống. Nếu bạn đang viết một tập lệnh có thể được thực thi sớm trong khi thiết lập một loại môi trường ảo nào đó, bạn có thể cần đảm bảo rằng PATH
không trống và được xuất: nếu PATH
vẫn chưa được đặt , sau đó một cái gì đó như PATH=$PATH:/some/directory
sẽ đặt PATH
thành :/some/directory
và thành phần trống ở đầu có nghĩa là thư mục hiện tại (như .:/some/directory
).
if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi
Trong bash, ksh và zsh, export
là cú pháp đặc biệt và cả PATH=~/opt/bin:$PATH
và export PATH=~/opt/bin:$PATH
làm điều đúng ngay cả. Trong các shell kiểu Bourne/POSIX khác, chẳng hạn như dấu gạch ngang (đó là /bin/sh
trên nhiều hệ thống), export
được phân tích cú pháp như một lệnh thông thường, hàm ý hai điểm khác biệt:
~
chỉ được phân tích cú pháp ở đầu Word, ngoại trừ trong các bài tập (xem Cách thêm đường dẫn thư mục chính được Unix phát hiện ra lệnh nào? để biết chi tiết);$PATH
bên ngoài dấu ngoặc kép ngắt nếu PATH
chứa khoảng trắng hoặc \[*?
.Vì vậy, trong vỏ như dấu gạch ngang, đặt export PATH=~/opt/bin:$PATH
PATH
thành chuỗi ký tự ~/opt/bin/:
theo sau là giá trị của PATH
cho đến khoảng trắng đầu tiên. PATH=~/opt/bin:$PATH
(một bài tập trần) không yêu cầu dấu ngoặc kép và thực hiện đúng. Nếu bạn muốn sử dụng export
trong tập lệnh di động, bạn cần viết export PATH="$HOME/opt/bin:$PATH"
, hoặc là PATH=~/opt/bin:$PATH; export PATH
(hoặc là PATH=$HOME/opt/bin:$PATH; export PATH
về tính di động đối với ngay cả Bourne Shell không chấp nhận export var=value
và không làm mở rộng dấu ngã).
¹ Điều này không đúng trong các vỏ Bourne (như trong Bourne Shell thực tế, không phải là các vỏ kiểu POSIX hiện đại), nhưng bạn rất khó gặp phải các vỏ cũ như vậy ngày nay.
Dù bằng cách nào, nhưng chúng không làm điều tương tự: các yếu tố của PATH
được kiểm tra từ trái sang phải. Trong ví dụ đầu tiên của bạn, các tệp thực thi trong ~/opt/bin
sẽ được ưu tiên hơn các cài đặt, ví dụ, trong /usr/bin
, có thể hoặc không thể là thứ bạn muốn.
Cụ thể, từ quan điểm an toàn, sẽ rất nguy hiểm khi thêm đường dẫn vào phía trước, bởi vì nếu ai đó có thể có quyền truy cập ghi vào ~/opt/bin
của bạn, ví dụ, họ có thể đặt ls
khác trong đó, mà sau đó bạn có thể sử dụng thay vì /bin/ls
mà không nhận thấy. Bây giờ hãy tưởng tượng tương tự cho ssh
hoặc trình duyệt hoặc lựa chọn của bạn ... (Điều tương tự cũng xảy ra khi đặt. Trong đường dẫn của bạn.)
Tôi bối rối bởi câu hỏi 2 (vì đã bị xóa khỏi câu hỏi vì đó là do một vấn đề không liên quan):
Cách nào khả thi để nối thêm đường dẫn trên các dòng khác nhau? Ban đầu tôi nghĩ rằng điều này có thể thực hiện các mẹo:
export PATH=$PATH:~/opt/bin export PATH=$PATH:~/opt/node/bin
nhưng không phải vì bài tập thứ hai không chỉ nối thêm
~/opt/node/bin
, nhưng cũng là toàn bộPATH
được gán trước đó.Đây là một cách giải quyết có thể:
export PATH=$PATH:~/opt/bin:~/opt/node/bin
nhưng để dễ đọc, tôi muốn có một nhiệm vụ cho một đường dẫn.
Nếu bạn nói
PATH=~/opt/bin
đó là tất cả đó sẽ nằm trong ĐƯỜNG của bạn. PATH chỉ là một biến môi trường và nếu bạn muốn thêm vào PATH, bạn phải xây dựng lại biến với chính xác nội dung bạn muốn. Đó là, những gì bạn đưa ra làm ví dụ cho câu hỏi 2 chính xác là những gì bạn muốn làm, trừ khi tôi hoàn toàn thiếu quan điểm của câu hỏi.
Tôi sử dụng cả hai hình thức trong mã của tôi. Tôi có một hồ sơ chung mà tôi cài đặt trên mọi máy tôi làm việc trông giống như thế này, để phù hợp với các thư mục có khả năng bị thiếu:
export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11
# add optional items to the path
for bindir in $HOME/local/bin $HOME/bin; do
if [ -d $bindir ]; then
PATH=$PATH:${bindir}
fi
done
Linux xác định đường dẫn tìm kiếm thực thi với $PATH
biến môi trường. Để thêm thư mục/dữ liệu/myscripts vào đầu $PATH
biến môi trường, sử dụng như sau:
PATH=/data/myscripts:$PATH
Để thêm thư mục đó vào cuối đường dẫn, sử dụng lệnh sau:
PATH=$PATH:/data/myscripts
Nhưng điều trước là không đủ vì khi bạn đặt biến môi trường bên trong tập lệnh, thay đổi đó chỉ có hiệu lực trong tập lệnh. Chỉ có hai cách xung quanh giới hạn này:
Ví dụ:
$HOME/myscript.sh
source $HOME/myscript.sh
Về cơ bản, việc kết hợp kịch bản "được gọi" trong tập lệnh "gọi". Nó giống như một #incoide trong C. Vì vậy, nó có hiệu quả trong tập lệnh hoặc chương trình "gọi". Nhưng tất nhiên, nó không hiệu quả trong bất kỳ chương trình hoặc tập lệnh nào được gọi bởi chương trình gọi. Để làm cho nó hiệu quả trong suốt chuỗi cuộc gọi, bạn phải tuân theo cài đặt của biến môi trường bằng lệnh xuất.
Ví dụ, chương trình bash Shell kết hợp nội dung của tệp .bash_profile bằng cách đưa vào. Đặt 2 dòng sau vào .bash_profile:
PATH=$PATH:/data/myscripts
export PATH
có hiệu quả đặt 2 dòng mã đó trong chương trình bash. Vì vậy, trong bash, biến $ PATH bao gồm $HOME/myscript.sh
và vì câu lệnh xuất, bất kỳ chương trình nào được gọi bởi bash đều bị thay đổi $PATH
Biến đổi. Và bởi vì bất kỳ chương trình nào bạn chạy từ bash Prompt đều được gọi bằng bash, đường dẫn mới có hiệu lực cho mọi thứ bạn chạy từ bash Prompt.
Điểm mấu chốt là để thêm một thư mục mới vào đường dẫn, bạn phải nối hoặc thêm thư mục vào biến môi trường $ PATH trong tập lệnh có trong Shell và bạn phải xuất $PATH
biến môi trường.
Thêm thông tin tại đây
Lâu nay tôi đã giữ cho tôi hai hàm pathadd
và pathrm
hỗ trợ thêm các phần tử vào đường dẫn mà không cần phải lo lắng về việc sao chép.
pathadd
nhận một đối số đường dẫn duy nhất và một đối số after
tùy chọn mà nếu được cung cấp sẽ nối với PATH
nếu không, nó sẽ bổ sung cho nó.
Trong hầu hết mọi tình huống nếu bạn thêm vào đường dẫn thì có khả năng bạn muốn ghi đè mọi thứ đã có trong đường dẫn, đó là lý do tại sao tôi chọn không trả trước theo mặc định.
pathadd() {
newelement=${1%/}
if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then
if [ "$2" = "after" ] ; then
PATH="$PATH:$newelement"
else
PATH="$newelement:$PATH"
fi
fi
}
pathrm() {
PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}
Đặt chúng trong bất kỳ tập lệnh nào bạn muốn thay đổi môi trường PATH và bây giờ bạn có thể làm.
pathadd "/foo/bar"
pathadd "/baz/bat" after
export PATH
Bạn được đảm bảo không thêm vào đường dẫn nếu nó đã ở đó. Nếu bây giờ bạn muốn đảm bảo /baz/bat
là lúc bắt đầu.
pathrm "/baz/bat"
pathadd "/baz/bat"
export PATH
Bây giờ bất kỳ đường dẫn nào cũng có thể được di chuyển ra phía trước nếu nó đã ở trong đường dẫn mà không cần nhân đôi.
Tôi không thể nói cho các bản phân phối khác, nhưng Ubuntu có một tệp,/etc/môi trường, đó là đường dẫn tìm kiếm mặc định cho tất cả người dùng. Vì máy tính của tôi chỉ được tôi sử dụng, tôi đặt bất kỳ thư mục nào tôi muốn trong đường dẫn của mình ở đó, trừ khi đó là một bổ sung tạm thời mà tôi đặt trong một tập lệnh.
Có một số tình huống sử dụng PATH=/a/b:$PATH
có thể được coi là cách "không chính xác" để thêm đường dẫn vào PATH
:
PATH
ở dạng tương tự.PATH
ở dạng khác (nghĩa là bí danh do sử dụng liên kết tượng trưng hoặc ..
).PATH
khi dự định ghi đè các mục khác trong PATH
.Hàm này (chỉ dành cho Bash) thực hiện "điều đúng" trong các tình huống trên (với một ngoại lệ, xem bên dưới), trả về mã lỗi và in thông điệp Nice cho con người. Mã lỗi và thông báo có thể bị vô hiệu hóa khi chúng không muốn.
prepath() {
local usage="\
Usage: prepath [-f] [-n] [-q] DIR
-f Force dir to front of path even if already in path
-n Nonexistent dirs do not return error status
-q Quiet mode"
local tofront=false errcode=1 qecho=echo
while true; do case "$1" in
-f) tofront=true; shift;;
-n) errcode=0; shift;;
-q) qecho=':'; shift;;
*) break;;
esac; done
# Bad params always produce message and error code
[[ -z $1 ]] && { echo 1>&2 "$usage"; return 1; }
[[ -d $1 ]] || { $qecho 1>&2 "$1 is not a directory."; return $errcode; }
dir="$(command cd "$1"; pwd -P)"
if [[ :$PATH: =~ :$dir: ]]; then
$tofront || { $qecho 1>&2 "$dir already in path."; return 0; }
PATH="${PATH#$dir:}" # remove if at start
PATH="${PATH%:$dir}" # remove if at end
PATH="${PATH//:$dir:/:}" # remove if in middle
fi
PATH="$dir:$PATH"
}
Ngoại lệ là hàm này không hợp quy hóa các đường dẫn được thêm vào PATH
thông qua các phương tiện khác, vì vậy nếu bí danh không chính tắc cho một đường dẫn nằm trong PATH
, thì điều này sẽ thêm một bản sao. Cố gắng chuẩn hóa các đường dẫn đã có trong PATH
là một đề xuất khó khăn vì một đường dẫn tương đối có ý nghĩa rõ ràng khi được chuyển đến prepath
nhưng khi đã ở trong đường dẫn, bạn không biết thư mục làm việc hiện tại là gì khi nó được thêm vào.
Để thêm một đường dẫn mới vào biến môi trường PATH
:
export PATH=$PATH:/new-path/
Để thay đổi này được áp dụng cho mọi Shell bạn mở, hãy thêm nó vào tệp mà Shell sẽ nguồn khi nó được gọi. Trong các shell khác nhau, điều này có thể là:
ví dụ.
# export PATH=$PATH:/root/learning/bin/
# source ~/.bashrc
# echo $PATH
Bạn có thể thấy đường dẫn được cung cấp trong đầu ra ở trên.
Đối với tôi (trên Mac OS X 10.9.5), thêm tên đường dẫn (ví dụ: /mypathname
) vào tệp /etc/paths
làm việc rất tốt.
Trước khi chỉnh sửa, echo $PATH
trả về:
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
Sau khi chỉnh sửa /etc/paths
và khởi động lại Shell, biến $ PATH được nối với /pathname
. Thật, echo $PATH
trả về:
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname
Điều gì đã xảy ra là /mypathname
đã được thêm vào $PATH
Biến đổi.
Đây là giải pháp của tôi:
PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")
Một lớp lót dễ dàng đẹp mà không để lại dấu vết :