Hapus jalur redundan dari variabel $ PATH


125

Saya telah menetapkan jalur yang sama dalam variabel $ PATH 6 kali.

Saya tidak keluar untuk memeriksa apakah itu berhasil.

Bagaimana cara menghapus duplikat?

Variabel $ PATH terlihat seperti ini:

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

Bagaimana cara meresetnya menjadi hanya

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

di mana Anda telah mendefinisikannya 6 kali? di file mana?
hovanessyan


Jawaban:


122

Anda baru saja mengeksekusi:

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

itu untuk sesi saat ini, jika Anda ingin mengubahnya secara permanen tambahkan ke .bashrc, bash.bashrc, / etc / profile - apapun yang sesuai dengan kebutuhan sistem dan pengguna Anda.

Catatan: Ini untuk Linux. Kami akan menjelaskan ini untuk pembuat kode baru. (',') Jangan mencoba SET = ini.


ya, saya mengaturnya secara permanen di bash.bashrc. Jadi, haruskah perintahnya seperti ini? echo 'export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' >> ~/.bashrc
Charles Hendry

masalahnya adalah bahwa tergantung pada OS Anda, rangkaian konfigurasi dijalankan. Anda perlu memastikan variabel PATH tidak ditimpa nanti. Cara termudah untuk melakukannya (untuk satu pengguna) adalah dengan menimpanya di .bashrc pribadi pengguna, yang biasanya terletak di direktori home-nya.
hovanessyan

1
perintah Anda menyetel PATH ke - $ PATH (nilai PATH saat ini) + string / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / usr / gam‌ es. Jika Anda hanya ingin memiliki String, hapus $ PATH + titik koma (:) dari perintah Anda. Tidak masalah jika Anda menggunakan echo atau mengedit file ~ / .bashrc secara manual.
hovanessyan

file bash.bashrc terletak di folder / etc. Itu tidak menampilkan variabel $ PATH, jadi saya tidak yakin di mana untuk mengeditnya
charles hendry

dalam komentar pertama Anda, Anda echo ke ~ / .bashrc (mengutip: >> ~ / .bashrc), bukan ke /etc/bash.bashrc. Jika Anda ingin mengubah PATH untuk pengguna tertentu, edit di / home / <nama pengguna> /. Bashrc file. /etc/bash.bashrc berlaku untuk semua pengguna.
hovanessyan

70

Jika Anda menggunakan Bash, Anda juga dapat melakukan hal berikut jika, katakanlah, Anda ingin menghapus direktori /home/wrong/dir/dari PATHvariabel Anda :

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

1
Ini berguna bagi saya, karena direktori telah ditambahkan di / etc / profile yang ingin saya kecualikan, tetapi tidak memiliki akses tulis ke / etc. Terima kasih :)
Samizdis

13
Protip: Anda dapat menggunakan pembatas berbeda dalam ekspresi sed untuk menghindari \ / melarikan diri:PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||')
iNecas

4
Trik ini membantu ketika saya ingin memiliki PATH baru segera, dan tidak ingin keluar dari terminal saat ini. Namun, untuk menghindari kesalahan, seseorang harus bereksperimen dengan perintah penghasil PATH (yaitu echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//') sebelum menugaskannya ke PATH.
biocyberman

2
Ini tidak akan berfungsi ketika jalur yang akan dihapus kebetulan adalah jalur pertama $PATH. Gunakan yang ini:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//')
Robin Hsu

tidak berhasil $ PATH=echo $ PATH | sed -e 's /: \ / scratch \ / sjn \ / anaconda \ / bin \ / python \ / $ //' "untuk menghapus / scratch / sjn / anaconda / bin / python
Mona Jalal

13

Linux: Hapus jalur redundan dari variabel $ PATH

Linux From Scratch memiliki fungsi ini di / 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"
}

Ini dimaksudkan untuk digunakan dengan fungsi berikut untuk menambahkan ke jalur, sehingga Anda tidak melakukannya secara berlebihan:

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"
}

Penggunaan sederhana adalah hanya memberikan pathremovejalur direktori untuk dihapus - tetapi perlu diingat bahwa itu harus sama persis:

$ pathremove /home/username/anaconda3/bin

Ini akan menghapus setiap instance dari direktori itu dari jalur Anda.

Jika Anda menginginkan direktori di jalur Anda, tetapi tanpa redundansi, Anda bisa menggunakan salah satu fungsi lain, misalnya - untuk kasus khusus Anda:

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

Tapi, kecuali keterbacaan menjadi perhatian, pada titik ini Anda lebih baik hanya melakukan:

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

Akankah hal di atas berhasil di semua cangkang yang diketahui manusia?

Aku akan menganggap di atas untuk bekerja di sh, dashdan bashsetidaknya. Saya akan terkejut mengetahui bahwa itu tidak berhasil csh, fish', orksh`. Saya ragu itu akan bekerja di shell perintah Windows atau Powershell.

Jika Anda memiliki Python, perintah semacam berikut harus melakukan apa yang diminta secara langsung (yaitu, hapus jalur yang berlebihan):

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

Satu baris (untuk menghindari masalah multiline):

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

Di atas menghapus jalur redundan kemudian. Untuk menghapus jalur redundan sebelumnya, gunakan indeks daftar terbalik dan balikkan lagi:

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

+1. apakah pathremove () berfungsi di semua shell, seperti, csh, ksh, bash, dll? btw, my / etc / profile di RHEL tidak memiliki partremove (), tetapi hanya memiliki pathmunge ().
Tagar

1
@Tagar Saya tidak menjamin kompatibilitas dengan semua shell lainnya. Saya sarankan mengujinya pada shell apa pun yang Anda gunakan, dan jika itu tidak berfungsi untuk shell Anda, Anda dapat menggunakan Python jika Anda telah menginstalnya - Saya menambahkan beberapa Python ke jawaban untuk menjelaskan caranya.
Aaron Hall

Jika saya membaca "3.5.3 Shell Parameter Expansion" dengan benar, ${!PATHVARIABLE}itu semacam tipuan variabel, tapi saya tidak yakin cara kerjanya di sini. Bisakah Anda menjelaskannya?
loxaxs

@loxaxs Itu adalah variabel lokal dalam fungsi bash tersebut, dideklarasikan dengan localbuiltin (yang hanya dapat digunakan di dalam fungsi.) Jika Anda memiliki pertanyaan lebih lanjut, Anda mungkin harus mengajukan pertanyaan baru di situs (setelah mencarinya terlebih dahulu untuk memastikan Anda tidak membuat duplikat persis ...).
Aaron Hall

Ini adalah jawaban yang sangat menarik, terima kasih atas artikelnya! Namun, pertanyaan asli untuk membersihkan variabel PATH yang kacau tampaknya tidak diselesaikan dengan elegan (meskipun, saya akui, maka ketika menggunakan fungsi ini seseorang tidak akan berakhir dengan PATH yang kacau untuk memulai).
Christian Herenz

9

Berikut adalah kode satu baris yang membersihkan PATH

  • Itu tidak mengganggu urutan PATH, hanya menghapus duplikat
  • Memperlakukan: dan mengosongkan PATH dengan anggun
  • Tidak ada karakter khusus yang digunakan, jadi tidak memerlukan pelarian
  • Menggunakan /bin/awksehingga berfungsi bahkan saat PATH rusak

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

1
ada yang mengujinya? aman?
Joe RR

2
jika Anda tidak menginstal awk itu membersihkan jalur Anda, saya sarankan menyalin jalur Anda ke file txt sebelumnya dengan echo $ PATH
Jose Pita

Tidak berfungsi untuk saya ... Saya telah menginstal awk, tetapi beberapa duplikat tidak dihapus.
Christian Herenz

3
  1. Hanya echo $PATH
  2. salin detailnya ke editor teks
  3. hapus entri yang tidak diinginkan
  4. PATH= # pass new list of entries

2

Jika Anda hanya ingin menghapus jalur duplikat, saya menggunakan skrip yang saya tulis beberapa waktu lalu karena saya mengalami masalah dengan beberapa jalur 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"

Dan saya menaruhnya di profil ~ /. Saya di bagian akhir. Karena saya menggunakan BASH hampir secara eksklusif, saya belum mencobanya di shell lain.


1
1 untuk solusinya. Btw, itu hanya akan menghapus jalur duplikasi jika mereka masuk daftar satu demi satu. Anda dapat mengubah |uniqke |sort|uniquntuk memperbaiki ini, tetapi ini akan mengubah urutan semua direktori di jalur yang menurut saya bukan efek samping yang diinginkan.
Tagar

1

Dengan asumsi shell Anda adalah Bash, Anda dapat mengatur jalurnya dengan

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

tetapi seperti yang dikatakan Levon dalam jawaban lain, segera setelah Anda menghentikan shell, perubahan akan hilang. Anda mungkin ingin mengatur PATHdalam ~/.bash_profileatau ~/.bashrc.


1

Di bash Anda cukup $ {var / find / replace}

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

Atau dalam kasus ini (karena bit ganti kosong) cukup:

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

Saya datang ke sini lebih dulu tetapi pergi ke tempat lain karena saya pikir akan ada perluasan parameter untuk melakukan ini. Lebih mudah dari sed !.

Bagaimana cara mengganti karakter placeholder atau kata dalam variabel dengan nilai dari variabel lain di Bash?


%Berarti cocok jika di akhir string, #adalah untuk awal.
sabgenton

0

Tidak ada alat standar untuk "mengedit" nilai $PATH(yaitu "tambahkan folder hanya jika belum ada" atau "hapus folder ini").

Untuk memeriksa apa jalurnya saat Anda masuk di lain waktu, gunakan telnet localhost(atau telnet 127.0.0.1). Ini kemudian akan meminta nama pengguna dan kata sandi Anda.

Ini memberi Anda shell login baru (yaitu yang benar-benar baru yang tidak mewarisi apa pun dari lingkungan saat ini).

Anda dapat memeriksa nilai di $PATHsana dan mengedit file rc Anda sampai benar. Ini juga berguna untuk melihat apakah Anda bisa login lagi setelah melakukan perubahan pada file penting.


Daripada harus mengetikkan nama pengguna / kata sandi, cukup ketik /bin/bash -i. Jauh lebih mudah.
Ed Heal

0

Bagaimana Anda menambahkan jalur duplikat ini ke variabel PATH Anda? Anda pasti sudah mengedit salah satu .file Anda . ( .tcshrc, atau .bashrc, dll tergantung pada sistem / shell Anda). Cara untuk memperbaikinya adalah dengan mengedit file lagi dan menghapus jalur duplikat.

Jika Anda tidak mengedit file apa pun, dan Anda pasti sudah memodifikasi PATH secara interaktif. Dalam hal ini perubahan tidak akan "melekat", yaitu jika Anda membuka shell lain, atau keluar dan masuk kembali, perubahan akan hilang secara otomatis.

Perhatikan bahwa ada beberapa file konfigurasi seluruh sistem juga, tetapi tidak mungkin Anda mengubahnya, jadi kemungkinan besar Anda akan mengubah file di direktori home pribadi Anda (jika Anda ingin membuat perubahan itu permanen setelah Anda menyelesaikan serangkaian jalur)


0

Untuk template copy-paste yang mudah saya menggunakan potongan Perl ini:

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

Dengan cara ini Anda tidak perlu keluar dari garis miring untuk operator pengganti.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.