Làm thế nào tôi có thể thêm sạch vào $ PATH?


31

Tôi muốn một cách để thêm mọi thứ vào $ PATH, toàn hệ thống hoặc cho một người dùng cá nhân, mà không có khả năng thêm cùng một đường dẫn nhiều lần.

Một lý do để muốn làm điều này là để bổ sung có thể được thực hiện .bashrc, không yêu cầu đăng nhập và cũng hữu ích hơn trên các hệ thống sử dụng (ví dụ) lightdm, không bao giờ gọi .profile.

Tôi biết các câu hỏi liên quan đến cách xóa các bản sao khỏi $ PATH, nhưng tôi không muốn xóa các bản sao . Tôi muốn một cách để thêm đường dẫn chỉ khi chúng chưa có mặt.



goldi, tôi không biết tại sao nhưng tôi đã thấy bình luận đầu tiên của bạn ngay cả khi trống rỗng. Nhưng có, tiền tố tên cũng hoạt động, không phải lo lắng! Đóng cửa theo cách khác là tốt.
Ciro Santilli 心 心

Được rồi, miễn là bạn nhận được tin nhắn của tôi. Đôi khi thực hiện một sự đảo ngược như thế này gây ra một chút hỗn loạn, tôi đoán chúng ta sẽ thấy điều gì xảy ra.
goldilocks

Câu trả lời:


35

Giả sử rằng đường dẫn mới mà chúng ta muốn thêm là:

new=/opt/bin

Sau đó, bằng cách sử dụng bất kỳ shell POSIX nào, chúng tôi có thể kiểm tra xem liệu newđã có trong đường dẫn chưa và thêm nó nếu nó không:

case ":${PATH:=$new}:" in
    *:"$new":*)  ;;
    *) PATH="$new:$PATH"  ;;
esac

Lưu ý việc sử dụng dấu hai chấm. Không có dấu hai chấm, chúng ta có thể nghĩ rằng, giả sử, new=/binđã nằm trong đường dẫn bởi vì mẫu này khớp với /usr/bin. Trong khi PATH thường có nhiều phần tử, các trường hợp đặc biệt bằng 0 và một phần tử trong PATH cũng được xử lý. Trường hợp PATH ban đầu không có phần tử (bị trống) được xử lý bằng cách sử dụng phần tử ${PATH:=$new}gán PATHcho $newnếu nó trống. Đặt giá trị mặc định cho tham số theo cách này là một tính năng của tất cả các vỏ POSIX: xem phần 2.6.2 của tài liệu POSIX .)

Một chức năng có thể gọi

Để thuận tiện, mã trên có thể được đưa vào một chức năng. Hàm này có thể được xác định tại dòng lệnh hoặc, để có sẵn vĩnh viễn, đưa vào tập lệnh khởi tạo shell của bạn (Đối với người dùng bash, điều đó sẽ là ~/.bashrc):

pupdate() { case ":${PATH:=$1}:" in *:"$1":*) ;; *) PATH="$1:$PATH" ;; esac; }

Để sử dụng chức năng cập nhật đường dẫn này để thêm một thư mục vào PATH hiện tại:

pupdate /new/path

@hammar OK. Tôi đã thêm một trường hợp cho điều đó.
John1024

1
Bạn có thể lưu 2 phân biệt trường hợp - cf unix.stackexchange.com/a/40973/1131 .
maxschlepzig

3
Nếu PATHtrống, điều này sẽ thêm một mục trống (tức là thư mục hiện tại) vào PATH. Tôi nghĩ bạn cần một trường hợp khác.
CB Bailey

2
@CharlesBailey Không khác case. Cứ làm đi case "${PATH:=$new}". Xem câu trả lời của riêng tôi cho các dự phòng tương tự.
mikeerv

1
@ mc0e Tôi đã thêm một ví dụ về cách sử dụng hàm shell để ẩn "nhiễu đường truyền".
John1024

9

Tạo một tệp trong /etc/profile.dđược gọi, ví dụ, mypath.sh(hoặc bất cứ điều gì bạn muốn). Nếu bạn đang sử dụng lightdm, hãy đảm bảo rằng điều đó khả thi hoặc người khác sử dụng /etc/bashrchoặc một tệp có nguồn gốc từ cùng. Thêm vào đó là các chức năng sau:

checkPath () {
        case ":$PATH:" in
                *":$1:"*) return 1
                        ;;
        esac
        return 0;
}

# Prepend to $PATH
prependToPath () {
        for a; do
                checkPath $a
                if [ $? -eq 0 ]; then
                        PATH=$a:$PATH
                fi
        done
        export PATH
}

# Append to $PATH
appendToPath () {
        for a; do
                checkPath $a
                if [ $? -eq 0 ]; then
                        PATH=$PATH:$a
                fi
        done
        export PATH
}

Những thứ ở đầu (được chuẩn bị trước) $ PATH được ưu tiên hơn những gì tiếp theo, và ngược lại, những thứ ở cuối (được nối thêm) sẽ được thay thế bởi những gì đến trước. Điều này có nghĩa là nếu $ PATH của bạn /usr/local/bin:/usr/binvà có một tệp thực thi gotchatrong cả hai thư mục, thì thư mục trong /usr/local/binsẽ được sử dụng theo mặc định.

Bây giờ bạn có thể - trong cùng tệp này, trong tệp cấu hình shell khác hoặc từ dòng lệnh - sử dụng:

appendToPath /some/path /another/path
prependToPath /some/path /yet/another/path

Nếu điều này nằm trong một .bashrc, nó sẽ ngăn giá trị xuất hiện nhiều hơn một lần khi bạn bắt đầu một vỏ mới. Có một hạn chế là nếu bạn muốn nối thêm thứ gì đó đã được chuẩn bị trước (tức là di chuyển một đường dẫn trong $ PATH) hoặc ngược lại, bạn sẽ phải tự làm điều đó.


chia tách $PATHvới IFS=:cuối cùng là linh hoạt hơn case.
mikeerv

@mikeerv Không còn nghi ngờ gì nữa. Đây là một loại hack sử dụng cho case, IMO. Tôi tưởng tượng awkcó thể được sử dụng tốt ở đây quá.
goldilocks

Đó là một điểm hay. Và, như tôi nghĩ, gawkcó thể trực tiếp chỉ định $PATH.
mikeerv

5

Bạn có thể làm theo cách này:

echo $PATH | grep /my/bin >/dev/null || PATH=$PATH:/my/bin

Lưu ý: nếu bạn xây dựng PATH từ các biến khác, hãy kiểm tra xem chúng không trống, vì nhiều shell diễn giải "" như "." .


+1 Theo trang man -qđược POSIX yêu cầu cho grep, nhưng tôi không biết điều đó có nghĩa là vẫn còn một số greps (không phải POSIX) không có nó.
goldilocks

1
lưu ý rằng mẫu grep quá rộng. Cân nhắc sử dụng egrep -q "(^ | :) / my / bin (: | \ $)" thay vì grep / my / bin> / dev / null. Với sửa đổi đó, giải pháp của bạn là chính xác và tôi nghĩ rằng đây là một giải pháp dễ đọc hơn câu trả lời hiện đang được ưa thích từ @ john1024. Lưu ý rằng tôi đã sử dụng dấu ngoặc kép để bạn sử dụng thay thế thay thế/my/bin
mc0e

5

Phần quan trọng của mã là kiểm tra xem PATHcó chứa một đường dẫn cụ thể không:

printf '%s' ":${PATH}:" | grep -Fq ":${my_path}:"

Đó là, đảm bảo rằng mỗi con đường trong PATHđược giới hạn trên cả hai bên bởi các PATHdấu phân cách ( :), sau đó kiểm tra ( -q) cho dù các literal string ( -F) bao gồm một PATHphân cách, con đường của bạn, và một PATHtách tồn tại trong đó. Nếu không, bạn có thể thêm đường dẫn một cách an toàn:

if ! printf '%s' ":${PATH-}:" | grep -Fq ":${my_path-}:"
then
    PATH="${PATH-}:${my_path-}"
fi

Điều này phải tương thích POSIX và sẽ hoạt động với bất kỳ đường dẫn nào không chứa ký tự dòng mới. Sẽ phức tạp hơn nếu bạn muốn nó hoạt động với các đường dẫn chứa dòng mới trong khi tương thích POSIX, nhưng nếu bạn có một grephỗ trợ, -zbạn có thể sử dụng nó.


4

Tôi đã mang theo chức năng nhỏ này trong tôi trong nhiều ~/.profiletập tin trong nhiều năm. Tôi nghĩ rằng nó được viết bởi sysadmin trong phòng thí nghiệm tôi từng làm việc nhưng tôi không chắc chắn. Dù sao, nó cũng tương tự như cách tiếp cận của Goldilock nhưng hơi khác:

pathmunge () {
        if ! echo $PATH | /bin/grep -Eq "(^|:)$1($|:)" ; then
           if [ "$2" = "after" ] ; then
              PATH=$PATH:$1
           else
              PATH=$1:$PATH
           fi
        fi
}

Vì vậy, để thêm một thư mục mới vào đầu PATH:

pathmunge /new/path

và đến cuối cùng:

pathmunge /new/path after

Điều này làm việc cho tôi! Nhưng tôi đã đổi sang logic để đặt nó theo mặc định và ghi đè bằng "trước". :)
Kevin Pauli

pathmunge là một phần của phân phối centos linux / etc / profile, nó có một tham số trước và sau. Tôi không thấy nó trong Ubuntu 16 mới nhất của mình
Kemin Zhou

Có vẻ hoạt động tốt trên macOS 10.12 sau /bin/grep->grep
Ben Creasy

4

CẬP NHẬT:

Tôi nhận thấy câu trả lời của riêng bạn có một chức năng riêng biệt để thêm hoặc thêm vào $PATH. Tôi thích ý tưởng. Vì vậy, tôi đã thêm một chút xử lý đối số. Tôi cũng đặt _tên đúng cho nó:

_path_assign() { oFS=$IFS ; IFS=: ; add=$* ; unset P A ; A=
    set -- ${PATH:=$1} ; for p in $add ; do {
        [ -z "${p%-[AP]}" ] && { unset P A
                eval ${p#-}= ; continue ; }
        for d ; do [ -z "${d%"$p"}" ] && break
        done ; } || set -- ${P+$p} $* ${A+$p}
        done ; export PATH="$*" ; IFS=$oFS
}

% PATH=/usr/bin:/usr/yes/bin
% _path_assign \
    /usr/bin \
    /usr/yes/bin \
    /usr/bin/nope \
    -P \
    /usr/nope/bin \
    /usr/bin \
    -A \
    /nope/usr/bin \
    /usr/nope/bin

% echo $PATH

ĐẦU RA:

/usr/nope/bin:/usr/bin:/usr/yes/bin:/usr/bin/nope:/nope/usr/bin

Theo mặc định, nó sẽ được chỉnh -Asửa $PATH, nhưng bạn có thể thay đổi hành vi này để -Psửa chữa bằng cách thêm một vị trí -Ptrong danh sách các đối số của bạn. Bạn có thể chuyển nó trở lại -Appending bằng cách đưa nó một -Alần nữa.

EVAL AN TOÀN

Trong hầu hết các trường hợp, tôi khuyên mọi người nên tránh sử dụng eval. Nhưng điều này, tôi nghĩ, nổi bật như một ví dụ về việc sử dụng nó cho tốt. Trong trường hợp này, tuyên bố duy nhất eval có thể nhìn thấy là P=hoặc A=. Các giá trị của các đối số của nó được kiểm tra nghiêm ngặt trước khi nó được gọi. Đây là những gì eval dành cho.

assign() { oFS=$IFS ; IFS=: ; add=$* 
    set -- ${PATH:=$1} ; for p in $add ; do { 
        for d ; do [ -z "${d%"$p"}" ] && break 
        done ; } || set -- $* $p ; done
    PATH="$*" ; IFS=$oFS
}

Điều này sẽ chấp nhận nhiều đối số như bạn đưa ra và thêm từng đối số $PATHchỉ một lần và chỉ khi nó chưa được đưa vào $PATH. Nó chỉ sử dụng tập lệnh shell POSIX hoàn toàn di động, chỉ dựa vào phần mềm dựng sẵn và rất nhanh.

% PATH=/usr/bin:/usr/yes/bin
% assign \
    /usr/bin \
    /usr/yes/bin \
    /usr/nope/bin \
    /usr/bin \
    /nope/usr/bin \
    /usr/nope/bin

% echo "$PATH"
> /usr/bin:/usr/yes/bin:/usr/nope/bin:/nope/usr/bin

@ TAFKA'goldilocks 'xem bản cập nhật ở đây - bạn đã truyền cảm hứng cho tôi.
mikeerv

+1 Vì tò mò (có thể đây sẽ là một câu hỏi và trả lời riêng biệt tốt), ý tưởng cho rằng các _hàm tiền tố làm cho chúng "được đặt tên đúng" đến từ đâu? Trong các ngôn ngữ khác, nó thường chỉ ra một hàm toàn cầu bên trong (nghĩa là một hàm cần phải là toàn cục, nhưng không được sử dụng bên ngoài như một phần của API). Tên của tôi chắc chắn không phải là lựa chọn tuyệt vời, nhưng dường như tôi chỉ sử dụng _không giải quyết được các vấn đề va chạm - tốt hơn là giải quyết một không gian tên thực tế, ví dụ. mikeserv_path_assign().
goldilocks

@ TAFKA'goldilocks '- sẽ tốt hơn nếu có được cụ thể hơn với nó, nhưng tên càng dài thì càng ít sử dụng. Nhưng nếu bạn có bất kỳ nhị phân thực thi thích hợp nào có tiền tố _thì bạn cần phải chuyển đổi các trình quản lý gói. Trong mọi trường hợp, về cơ bản, đây chỉ là một "toàn cầu, nội bộ, chức năng" - nó là toàn cầu đối với mọi shell được gọi từ shell mà nó được khai báo và nó chỉ là một đoạn script ngôn ngữ được dịch ra trong bộ nhớ của trình thông dịch . unix.stackexchange.com/questions/120528/ Cách
mikeerv

Bạn có thể không unset a(hoặc tương đương) ở cuối hồ sơ?
nguồn

0

Kìa! Chức năng vỏ 12-line ... kỹ thuật bash- và zsh-Portable mạnh mẽ về mặt kỹ thuật , cực kỳ yêu thích kịch bản khởi động ~/.bashrchoặc ~/.zshrclựa chọn của bạn:

# void +path.append(str dirname, ...)
#
# Append each passed existing directory to the current user's ${PATH} in a
# safe manner silently ignoring:
#
# * Relative directories (i.e., *NOT* prefixed by the directory separator).
# * Duplicate directories (i.e., already listed in the current ${PATH}).
# * Nonextant directories.
+path.append() {
    # For each passed dirname...
    local dirname
    for   dirname; do
        # Strip the trailing directory separator if any from this dirname,
        # reducing this dirname to the canonical form expected by the
        # test for uniqueness performed below.
        dirname="${dirname%/}"

        # If this dirname is either relative, duplicate, or nonextant, then
        # silently ignore this dirname and continue to the next. Note that the
        # extancy test is the least performant test and hence deferred.
        [[ "${dirname:0:1}" == '/' &&
           ":${PATH}:" != *":${dirname}:"* &&
           -d "${dirname}" ]] || continue

        # Else, this is an existing absolute unique dirname. In this case,
        # append this dirname to the current ${PATH}.
        PATH="${PATH}:${dirname}"
    done

    # Strip an erroneously leading delimiter from the current ${PATH} if any,
    # a common edge case when the initial ${PATH} is the empty string.
    PATH="${PATH#:}"

    # Export the current ${PATH} to subprocesses. Although system-wide scripts
    # already export the ${PATH} by default on most systems, "Bother free is
    # the way to be."
    export PATH
}

Chuẩn bị cho mình vinh quang tức thời. Sau đó, thay vì làm điều này và mong muốn điều tốt nhất:

export PATH=$PATH:~/opt/bin:~/the/black/goat/of/the/woods/with/a/thousand/young

Thay vào đó, hãy làm điều này và được đảm bảo có được thứ tốt nhất, cho dù bạn có thực sự muốn điều đó hay không:

+path.append ~/opt/bin ~/the/black/goat/of/the/woods/with/a/thousand/young

Rất tốt, Xác định "Tốt nhất."

Bổ sung và chuẩn bị một cách an toàn vào hiện tại ${PATH}không phải là chuyện nhỏ mà nó thường được thực hiện. Mặc dù thuận tiện và có vẻ hợp lý, một trong những mẫu đơn export PATH=$PATH:~/opt/binmời các biến chứng ma quỷ với:

  • Vô tình dirnames tương đối (ví dụ, export PATH=$PATH:opt/bin). Trong khi bashzshâm thầm chấp nhận và chủ yếu bỏ qua các dirnam tương đối trong hầu hết các trường hợp, các dirnam tương đối được tiền tố bởi một trong hai ( hhoặc tcó thể các nhân vật bất chính khác) khiến cả hai phải xấu hổ tự cắt xén kiệt tác bán kết năm 1962 của Masaki Kobayashi Harakiri :

    # Don't try this at home. You will feel great pain.
    $ PATH='/usr/local/bin:/usr/bin:/bin' && export PATH=$PATH:harakiri && echo $PATH
    /usr/local/bin:/usr/bin:arakiri
    $ PATH='/usr/local/bin:/usr/bin:/bin' && export PATH=$PATH:tanuki/yokai && echo $PATH
    binanuki/yokai   # Congratulations. Your system is now face-up in the gutter.
  • Vô tình trùng lặp dirnames. Mặc dù các ${PATH}dirnam trùng lặp phần lớn là vô hại, chúng cũng không mong muốn, cồng kềnh, kém hiệu quả, cản trở khả năng sửa lỗi và thúc đẩy hao mòn ổ đĩa - giống như câu trả lời này. Mặc dù SSD kiểu NAND ( tất nhiên ) miễn nhiễm với đọc, nhưng ổ cứng thì không. Truy cập hệ thống tập tin không cần thiết trên mỗi lệnh đã thử ngụ ý hao mòn đầu đọc không cần thiết ở cùng một nhịp độ. Các bản sao đặc biệt không rõ ràng khi gọi các vỏ được lồng trong các quy trình lồng nhau, tại thời điểm đó, các lớp lót dường như vô hại như export PATH=$PATH:~/watnhanh chóng nổ tung vào Vòng tròn thứ bảy ${PATH}như địa ngục PATH=/usr/local/bin:/usr/bin:/bin:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat. Chỉ Beelzebubba có thể giúp bạn nếu sau đó bạn thêm các tên khác vào đó. (Đừng để điều này xảy ra với những đứa trẻ quý giá của bạn. )

  • Vô tình thiếu dirnames. Một lần nữa, trong khi thiếu các ${PATH}tên miền chủ yếu là vô hại, chúng cũng thường không mong muốn, cồng kềnh, kém hiệu quả, cản trở khả năng sửa lỗi và thúc đẩy hao mòn ổ đĩa.

Ergo, tự động hóa thân thiện như chức năng shell được xác định ở trên. Chúng ta phải tự cứu mình khỏi chính mình.

Nhưng ... Tại sao "+ path.append ()"? Tại sao không chỉ đơn giản là append_path ()?

Đối với tính không rõ ràng (ví dụ: với các lệnh bên ngoài trong các ${PATH}hàm shell hiện tại hoặc toàn hệ thống được xác định ở nơi khác), các hàm shell do người dùng định nghĩa là tiền tố hoặc hậu tố lý tưởng được hỗ trợ bởi bashzshnhưng bị cấm đối với các tên cơ sở lệnh tiêu chuẩn - như, giả sử +.

Chào. Nó hoạt động. Đừng phán xét tôi.

Nhưng ... Tại sao "+ path.append ()"? Tại sao không "+ path.prepend ()"?

Bởi vì nối thêm vào hiện tại ${PATH}an toàn hơn so với trả trước cho hiện tại ${PATH}, tất cả mọi thứ đều bình đẳng, điều mà chúng không bao giờ được. Việc ghi đè các lệnh trên toàn hệ thống bằng các lệnh dành riêng cho người dùng có thể không đảm bảo tốt nhất và làm cho điên rồ nhất. Ví dụ, trong Linux, các ứng dụng xuôi dòng thường mong đợi các biến thể lệnh lõi của GNU thay vì các dẫn xuất hoặc các lựa chọn thay thế không chuẩn.

Điều đó nói rằng, hoàn toàn có trường hợp sử dụng hợp lệ để làm như vậy. Xác định +path.prepend()hàm tương đương là tầm thường. Sans prolix nebulity, cho sự tỉnh táo chia sẻ của anh ấy và cô ấy:

+path.prepend() {
    local dirname
    for dirname in "${@}"; do
        dirname="${dirname%/}"
        [[ "${dirname:0:1}" == '/' &&
           ":${PATH}:" != *":${dirname}:"* &&
           -d "${dirname}" ]] || continue
        PATH="${dirname}:${PATH}"
    done
    PATH="${PATH%:}"
    export PATH
}

Nhưng ... Tại sao không phải là Gilles?

Câu trả lời được chấp nhận của Gilles ở nơi khác là tối ưu một cách ấn tượng trong trường hợp chung như là một "phần phụ bất khả tri bất khả tri" . Trong trường hợp chung của bashzshvới không Tuy nhiên, liên kết tượng trưng không mong muốn, hình phạt hiệu suất cần phải như vậy rất buồn các ricer Gentoo trong tôi. Ngay cả khi có sự hiện diện của các liên kết tượng trưng không mong muốn, vẫn còn tranh cãi liệu việc bỏ một chuỗi con trên mỗi add_to_PATH()đối số có đáng để chèn các liên kết trùng lặp tiềm năng hay không.

Đối với các trường hợp sử dụng nghiêm ngặt yêu cầu loại bỏ ngay cả các bản sao liên kết tượng trưng, zshbiến thể cụ thể này thực hiện điều đó thông qua các nội dung hiệu quả thay vì các nhánh không hiệu quả:

+path.append() {
    local dirname
    for   dirname in "${@}"; do
        dirname="${dirname%/}"
        [[ "${dirname:0:1}" == '/' &&
           ":${PATH}:" != *":${dirname:A}:"* &&
           -d "${dirname}" ]] || continue
        PATH="${PATH}:${dirname}"
    done
    PATH="${PATH#:}"
    export PATH
}

Lưu ý *":${dirname:A}:"*thay vì *":${dirname}:"*của bản gốc. :Alà một chủ nghĩa kỳ diệu zshđáng buồn vắng mặt dưới hầu hết các vỏ khác - bao gồm cả bash. Để trích dẫn man zshexpn:

Trả lời : Biến tên tệp thành một đường dẫn tuyệt đối như công cụ asửa đổi thực hiện, sau đó chuyển kết quả qua realpath(3)chức năng thư viện để giải quyết các liên kết tượng trưng. Lưu ý: trên các hệ thống không có realpath(3)chức năng thư viện, các liên kết tượng trưng không được giải quyết, do đó, trên các hệ thống đó aAtương đương.

Không có câu hỏi nào nữa.

Không có gì. Thưởng thức pháo kích an toàn. Bây giờ bạn xứng đáng với nó.


0

Đây là phiên bản kiểu lập trình chức năng của tôi.

  • Làm việc cho bất kỳ *PATHbiến phân định dấu hai chấm , không chỉ PATH.
  • Không truy cập nhà nước toàn cầu
  • Chỉ hoạt động với / trên đầu vào bất biến của nó
  • Tạo ra một đầu ra duy nhất
  • Không có tác dụng phụ
  • Có thể ghi nhớ (về nguyên tắc)

Cũng đáng chú ý:

  • Bất khả tri liên quan đến exporting; còn lại cho người gọi (xem ví dụ)
  • Tinh khiết bash; không rèn
path_add () {
  # $ 1: Phần tử cần đảm bảo nằm trong chuỗi đường dẫn đã cho chính xác một lần
  # $ 2: Giá trị chuỗi đường dẫn hiện có ("$ PATH", không phải "PATH")
  # $ 3 (tùy chọn, bất cứ điều gì): Nếu được cung cấp, hãy thêm $ 1; nếu không, hãy chuẩn bị
  #
  # Ví dụ:
  # $ export PATH = $ (path_add '/ opt / bin' "$ PATH")
  # $ CDPATH = $ (path_add '/ Âm nhạc' "$ CDPATH" at_end)

  cục bộ -r rồi_present = "(^ | :) $ {1} ($ | :)"
  if [["$ 2" = ~ $ yet_present]]; sau đó
    tiếng vang "$ 2"
  elif [[$ # == 3]]; sau đó
    tiếng vang "$ {2}: $ {1}"
  khác
    tiếng vang "$ {1}: $ {2}"
  fi
}

0

Kịch bản này cho phép bạn thêm vào cuối $PATH:

PATH=path2; add_to_PATH after path1 path2:path3
echo $PATH
path2:path1:path3

Hoặc thêm vào đầu $PATH:

PATH=path2; add_to_PATH before path1 path2:path3
echo $PATH
path1:path3:path2

# Add directories to $PATH iff they're not already there
# Append directories to $PATH by default
# Based on https://unix.stackexchange.com/a/4973/143394
# and https://unix.stackexchange.com/a/217629/143394
add_to_PATH () {
  local prepend  # Prepend to path if set
  local prefix   # Temporary prepended path
  local IFS      # Avoid restoring for added laziness

  case $1 in
    after)  shift;; # Default is to append
    before) prepend=true; shift;;
  esac

  for arg; do
    IFS=: # Split argument by path separator
    for dir in $arg; do
      # Canonicalise symbolic links
      dir=$({ cd -- "$dir" && { pwd -P || pwd; } } 2>/dev/null)
      if [ -z "$dir" ]; then continue; fi  # Skip non-existent directory
      case ":$PATH:" in
        *":$dir:"*) :;; # skip - already present
        *) if [ "$prepend" ]; then
           # ${prefix:+$prefix:} will expand to "" if $prefix is empty to avoid
           # starting with a ":".  Expansion is "$prefix:" if non-empty.
            prefix=${prefix+$prefix:}$dir
          else
            PATH=$PATH:$dir  # Append by default
          fi;;
      esac
    done
  done
  [ "$prepend" ] && [ "$prefix" != "" ] && PATH=$prefix:$PATH
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.