Xóa các đường dẫn dư thừa khỏi biến $ PATH


125

Tôi đã xác định cùng một đường dẫn trong biến $ PATH 6 lần.

Tôi đã không đăng xuất để kiểm tra xem nó có hoạt động không.

Làm thế nào tôi có thể loại bỏ các bản sao?

Biến $ PATH trông như thế này:

echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin

Làm thế nào tôi có thể thiết lập lại nó chỉ

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

bạn đã định nghĩa nó 6 lần ở đâu? trong tập tin nào?
hovanessyan


Câu trả lời:


122

Bạn chỉ cần thực hiện:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

đó sẽ là phiên hiện tại, nếu bạn muốn thay đổi vĩnh viễn, hãy thêm nó vào bất kỳ .bashrc, bash.bashrc, / etc / profile - bất cứ điều gì phù hợp với nhu cầu của hệ thống và người dùng của bạn.

Lưu ý: Đây là dành cho Linux. Chúng tôi sẽ làm rõ điều này cho các lập trình viên mới. (`, ') Đừng cố gắng SET = những cái này.


vâng, tôi đặt chúng vĩnh viễn trong bash.bashrc. Vì vậy, lệnh nên là một cái gì đó như thế này? echo 'export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' >> ~/.bashrc
charles hendry

điều này phụ thuộc vào hệ điều hành của bạn, một chuỗi các cấu hình được thực thi. Bạn cần đảm bảo biến PATH không bị ghi đè sau này. Cách dễ nhất để làm điều đó (đối với một người dùng) là ghi đè lên nó trong .bashrc cá nhân của người dùng, thường được đặt trong thư mục chính của anh ta.
hovanessyan

1
lệnh của bạn đặt PATH thành - $ PATH (giá trị hiện tại của PATH) + chuỗi / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / usr / gam‌ es. Nếu bạn muốn chỉ có Chuỗi, hãy xóa $ PATH + dấu chấm phẩy (:) khỏi lệnh của bạn. Sẽ không thành vấn đề nếu bạn sử dụng echo hoặc chỉnh sửa tệp ~ / .bashrc bằng tay.
hovanessyan

tệp bash.bashrc nằm trong thư mục / etc. Mặc dù vậy, nó không hiển thị biến $ PATH, vì vậy tôi không chắc chắn nên chỉnh sửa nó ở đâu
charles hendry

trong bình luận đầu tiên của bạn, bạn lặp lại ~ / .bashrc (trích dẫn: >> ~ / .bashrc), không phải /etc/bash.bashrc. Nếu bạn muốn thay đổi PATH cho một người dùng cụ thể, hãy chỉnh sửa nó trong / home / <tên của người dùng> /. Bashrc. /etc/bash.bashrc áp dụng cho tất cả người dùng.
hovanessyan

70

Nếu bạn đang sử dụng Bash, bạn cũng có thể thực hiện các thao tác sau nếu giả sử bạn muốn xóa thư mục /home/wrong/dir/khỏi PATHbiến của mình :

PATH=`echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'`

1
Điều này rất hữu ích với tôi, vì một thư mục đã được thêm vào / etc / profile mà tôi muốn loại trừ, nhưng không có quyền truy cập ghi vào / etc. Cảm ơn :)
Samizdis

13
Protip: bạn có thể sử dụng các dấu phân cách khác nhau trong biểu thức sed để tránh \ / thoát:PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||')
iNecas

4
Thủ thuật này giúp ích khi tôi muốn có PATH mới ngay lập tức và không muốn đăng xuất khỏi thiết bị đầu cuối hiện tại. Tuy nhiên, để tránh gây rối, người ta nên thử nghiệm với lệnh tạo PATH (tức là echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//') trước khi gán nó cho PATH.
biocyberman 1/5/2015

2
Điều này sẽ không hoạt động khi đường dẫn bị xóa xảy ra là đường dẫn đầu tiên $PATH. Sử dụng cái này:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//')
Robin Hsu

không làm việc $ PATH=vang vọng $ PATH | sed -e 's /: \ / scratch \ / sjn \ / anaconda \ / bin \ / python \ / $ //' `` để xóa / Scratch / sjn / anaconda / bin / python
Mona Jalal

13

Linux: Loại bỏ các đường dẫn dư thừa khỏi biến $ PATH

Linux From Scratch có chức năng này trong / etc / profile

# Functions to help us manage paths.  Second argument is the name of the
# path variable to be modified (default: PATH)
pathremove () {
        local IFS=':'
        local NEWPATH
        local DIR
        local PATHVARIABLE=${2:-PATH}
        for DIR in ${!PATHVARIABLE} ; do
                if [ "$DIR" != "$1" ] ; then
                  NEWPATH=${NEWPATH:+$NEWPATH:}$DIR
                fi
        done
        export $PATHVARIABLE="$NEWPATH"
}

Điều này được dự định sẽ được sử dụng với các chức năng này để thêm vào đường dẫn, do đó bạn không thực hiện nó một cách dư thừa:

pathprepend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}"
}

pathappend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1"
}

Cách sử dụng đơn giản là chỉ cần cung cấp pathremoveđường dẫn thư mục để xóa - nhưng hãy nhớ rằng nó phải khớp chính xác:

$ pathremove /home/username/anaconda3/bin

Điều này sẽ loại bỏ từng phiên bản của thư mục đó khỏi đường dẫn của bạn.

Nếu bạn muốn thư mục trong đường dẫn của mình, nhưng không có dự phòng, bạn chỉ có thể sử dụng một trong các chức năng khác, ví dụ - cho trường hợp cụ thể của bạn:

$ pathprepend /usr/local/sbin
$ pathappend /usr/local/bin
$ pathappend /usr/sbin
$ pathappend /usr/bin
$ pathappend /sbin
$ pathappend /bin
$ pathappend /usr/games

Nhưng, trừ khi khả năng đọc là mối quan tâm, tại thời điểm này, bạn nên làm tốt hơn:

$ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Những điều trên sẽ làm việc trong tất cả các vỏ được biết đến với con người?

Tôi sẽ đoán ở trên để làm việc trong sh, dashbashít nhất. Tôi sẽ ngạc nhiên khi biết nó không hoạt động csh, fish', orksh`. Tôi nghi ngờ nó sẽ hoạt động trong Windows shell shell hoặc Powershell.

Nếu bạn có Python, loại lệnh sau sẽ thực hiện những gì được yêu cầu trực tiếp (nghĩa là loại bỏ các đường dẫn dư thừa):

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')
print(':'.join(sorted(set(path), key=path.index)))
" )

Một lớp lót (để vượt qua các vấn đề đa dòng):

$ PATH=$( python -c "import os; path = os.environ['PATH'].split(':'); print(':'.join(sorted(set(path), key=path.index)))" )

Ở trên loại bỏ các đường dẫn dư thừa sau này. Để xóa các đường dẫn dự phòng trước đó, hãy sử dụng chỉ mục của danh sách đảo ngược và đảo ngược lại:

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')[::-1]
print(':'.join(sorted(set(path), key=path.index, reverse=True)))
" )

+1. pathremove () có hoạt động trong tất cả các hương vị vỏ, như, csh, ksh, bash vv không? btw, hồ sơ / etc / của tôi trên RHEL không có partremove (), mà chỉ có pathmunge ().
Tagar

1
@Tagar Tôi không đảm bảo về khả năng tương thích với tất cả các shell khác. Tôi khuyên bạn nên thử nghiệm nó trên bất kỳ shell nào bạn đang sử dụng và nếu nó không hoạt động cho shell của bạn, bạn có thể sử dụng Python nếu bạn đã cài đặt nó - Tôi đã thêm một số Python vào câu trả lời để mô tả cách làm.
Aaron Hall

Nếu tôi đọc chính xác "3.5.3 Mở rộng tham số Shell", ${!PATHVARIABLE}là một loại cảm ứng biến đổi, nhưng tôi không chắc nó hoạt động như thế nào ở đây. Bạn có thể giải thích nó được không?
loxaxs

@loxaxs Đó là một biến cục bộ trong các hàm bash đó, được khai báo bằng hàm localdựng sẵn (chỉ có thể được sử dụng bên trong một hàm.) Nếu bạn có thêm câu hỏi, có lẽ bạn nên đặt câu hỏi mới trên trang web (sau khi tìm kiếm trước để đảm bảo bạn không tạo một bản sao chính xác ...).
Aaron Hall

Đây là một câu trả lời thực sự thú vị, cảm ơn vì đã viết! Tuy nhiên, câu hỏi ban đầu về làm sạch biến PATH lộn xộn dường như không được giải quyết một cách thanh lịch (althoug, tôi thừa nhận, sau đó khi sử dụng chức năng này, người ta sẽ không bắt đầu với một PATH lộn xộn để bắt đầu).
Christian Herenz

9

Đây là mã một dòng giúp dọn sạch PATH

  • Nó không làm xáo trộn trật tự của PATH, chỉ loại bỏ các bản sao
  • Treats: và empth PATH duyên dáng
  • Không có ký tự đặc biệt được sử dụng, vì vậy không yêu cầu thoát
  • Sử dụng /bin/awkđể nó hoạt động ngay cả khi PATH bị hỏng

    export PATH="$(echo "$PATH" |/bin/awk 'BEGIN{RS=":";}
    {sub(sprintf("%c$",10),"");if(A[$0]){}else{A[$0]=1;
    printf(((NR==1)?"":":")$0)}}')";

1
có ai thử không? có an toàn không
Joe RR

2
nếu bạn chưa cài đặt nó, hãy dọn sạch đường dẫn của bạn, tôi khuyên bạn nên sao chép đường dẫn của mình sang tệp txt trước đó với echo $ PATH
Jose Pita

Không hoạt động đối với tôi ... Tôi đã cài đặt awk, nhưng một số bản sao không bị xóa.
Christian Herenz

3
  1. Chỉ echo $PATH
  2. sao chép chi tiết vào một trình soạn thảo văn bản
  3. loại bỏ các mục không mong muốn
  4. PATH= # pass new list of entries

2

Nếu bạn chỉ muốn xóa bất kỳ đường dẫn trùng lặp nào, tôi sử dụng tập lệnh này tôi đã viết lại một lúc vì tôi gặp sự cố với nhiều đường dẫn perl5 / bin:

#!/bin/bash
#
# path-cleanup
#
# This must be run as "source path-cleanup" or ". path-cleanup"
# so the current shell gets the changes.

pathlist=`echo $PATH | sed 's/:/\n/g' | uniq`

# echo "Starting PATH: $PATH"
# echo "pathlist: $pathlist"
unset PATH
# echo "After unset, PATH: $PATH"
for dir in $pathlist
do
    if test -d $dir ; then
        if test -z $PATH; then
            PATH=$dir
        else
            PATH=$PATH:$dir
        fi
    fi
done
export PATH
# echo "After loop, PATH: $PATH"

Và tôi đặt nó vào ~ / .profile của tôi ở cuối. Vì tôi sử dụng BASH gần như độc quyền, tôi đã không thử nó trong các shell khác.


1
+1 cho giải pháp. Btw, nó sẽ chỉ xóa các đường dẫn trùng lặp nếu chúng đi vào danh sách lần lượt. Bạn có thể thay đổi |uniqđể |sort|uniqsửa lỗi này, nhưng điều này sẽ thay đổi thứ tự của tất cả các thư mục trong đường dẫn mà tôi không nghĩ là một tác dụng phụ mong muốn.
Tagar

1

Giả sử shell của bạn là Bash, bạn có thể đặt đường dẫn với

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

nhưng giống như Levon đã nói trong một câu trả lời khác, ngay khi bạn chấm dứt lớp vỏ, những thay đổi sẽ biến mất. Bạn có thể muốn thiết lập của bạn PATHtrong ~/.bash_profilehoặc ~/.bashrc.


1

Trong bash, bạn chỉ cần $ {var / find / thay thế}

PATH=${PATH/%:\/home\/wrong\/dir\//}

Hoặc trong trường hợp này (vì bit thay thế trống) chỉ:

PATH=${PATH%:\/home\/wrong\/dir\/}

Tôi đến đây trước nhưng đã đi kho khác vì tôi nghĩ sẽ có một mở rộng tham số để làm điều này. Dễ dàng hơn sed!.

Làm thế nào để thay thế ký tự giữ chỗ hoặc từ trong biến bằng giá trị từ một biến khác trong Bash?


%có nghĩa là khớp nếu ở cuối chuỗi, #là bắt đầu.
sabgenton

0

Không có công cụ tiêu chuẩn nào để "chỉnh sửa" giá trị của $PATH(tức là "chỉ thêm thư mục khi nó chưa tồn tại" hoặc "xóa thư mục này").

Để kiểm tra đường dẫn sẽ là gì khi bạn đăng nhập lần sau, hãy sử dụng telnet localhost(hoặc telnet 127.0.0.1). Sau đó nó sẽ hỏi tên người dùng và mật khẩu của bạn.

Điều này cung cấp cho bạn một vỏ đăng nhập mới (tức là một vỏ hoàn toàn mới không kế thừa bất cứ thứ gì từ môi trường hiện tại).

Bạn có thể kiểm tra giá trị của $PATHnó và chỉnh sửa các tập tin RC của bạn cho đến khi nó chính xác. Điều này cũng hữu ích để xem liệu bạn có thể đăng nhập lại hay không sau khi thực hiện thay đổi thành một tệp quan trọng.


Thay vì phải nhập tên người dùng / mật khẩu, chỉ cần nhập /bin/bash -i . Ít rắc rối hơn nhiều.
Ed Heal

0

Làm thế nào bạn thêm các đường dẫn trùng lặp này vào biến PATH của bạn? Bạn phải chỉnh sửa một trong các .tập tin của bạn . ( .tcshrc, hoặc .bashrc, vv tùy thuộc vào hệ thống / vỏ cụ thể của bạn). Cách khắc phục là chỉnh sửa lại tệp và xóa các đường dẫn trùng lặp.

Nếu bạn không chỉnh sửa bất kỳ tệp nào và bạn phải sửa đổi PATH một cách tương tác. Trong trường hợp đó, các thay đổi sẽ không "dính", tức là nếu bạn mở một shell khác hoặc đăng xuất và đăng nhập lại, các thay đổi sẽ tự động biến mất.

Lưu ý rằng cũng có một số tệp cấu hình trên toàn hệ thống, nhưng không chắc là bạn đã sửa đổi các tệp đó, vì vậy rất có thể bạn sẽ thay đổi các tệp trong thư mục nhà riêng của mình (nếu bạn muốn thay đổi vĩnh viễn khi bạn giải quyết trên một bộ đường dẫn)


0

Đối với một mẫu sao chép-dán dễ dàng, tôi sử dụng đoạn mã Perl này:

PATH=`echo $PATH | perl -pe s:/path/to/be/excluded::`

Bằng cách này, bạn không cần phải thoát dấu gạch chéo cho toán tử thay thế.

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.