Saya ingin cara menambahkan sesuatu ke $ PATH, seluruh sistem atau untuk pengguna individu, tanpa berpotensi menambahkan jalur yang sama beberapa kali.
Salah satu alasan untuk ingin melakukan ini adalah agar penambahan dapat dibuat .bashrc
, yang tidak memerlukan login, dan juga lebih berguna pada sistem yang menggunakan (misalnya) lightdm
, yang tidak pernah menelepon .profile
.
Saya menyadari pertanyaan yang berhubungan dengan cara membersihkan duplikat dari $ PATH, tetapi saya tidak ingin menghapus duplikat . Saya ingin cara menambahkan jalur hanya jika belum ada.
Jawaban:
Misalkan jalur baru yang ingin kita tambahkan adalah:
Kemudian, menggunakan shell POSIX apa pun, kita dapat menguji untuk melihat apakah
new
sudah ada di path dan menambahkannya jika belum:Perhatikan penggunaan titik dua. Tanpa titik dua, kita mungkin berpikir bahwa, katakanlah,
new=/bin
sudah berada di jalan karena polanya cocok/usr/bin
. Walaupun PATH biasanya memiliki banyak elemen, kasus khusus nol dan satu elemen dalam PATH juga ditangani. Kasus PATH awalnya tidak memiliki elemen (kosong) ditangani dengan penggunaan${PATH:=$new}
yang ditugaskanPATH
untuk$new
jika kosong. Mengatur nilai default untuk parameter dengan cara ini adalah fitur dari semua shell POSIX: lihat bagian 2.6.2 dari dokumen POSIX .)Fungsi yang bisa dipanggil
Untuk kenyamanan, kode di atas dapat dimasukkan ke dalam suatu fungsi. Fungsi ini dapat didefinisikan pada baris perintah atau, agar tersedia secara permanen, dimasukkan ke dalam skrip inisialisasi shell Anda (Untuk pengguna bash, itu adalah
~/.bashrc
):Untuk menggunakan fungsi pembaruan jalur ini untuk menambahkan direktori ke PATH saat ini:
sumber
PATH
kosong, ini akan menambah entri kosong (yaitu direktori saat ini) kePATH
. Saya pikir Anda perlu kasus lain.case
. Lakukan sajacase "${PATH:=$new}"
. Lihat jawaban saya sendiri untuk fallback serupa.Buat file dengan
/etc/profile.d
nama, misalnya,mypath.sh
(atau apa pun yang Anda inginkan). Jika Anda menggunakan lightdm, pastikan itu layak atau menggunakan/etc/bashrc
file lain. Tambahkan ke bahwa fungsi-fungsi berikut:Hal-hal di awal (disesuaikan dengan) $ PATH didahulukan dari yang berikut, dan sebaliknya, hal-hal di akhir (ditambahkan) akan digantikan oleh apa yang datang sebelumnya. Ini berarti jika $ PATH Anda
/usr/local/bin:/usr/bin
dan ada yang dapat dieksekusigotcha
di kedua direktori, yang di/usr/local/bin
akan digunakan secara default.Anda sekarang dapat - dalam file yang sama ini, di file konfigurasi shell lain, atau dari commandline - gunakan:
Jika ini dalam a
.bashrc
, itu akan mencegah nilai muncul lebih dari sekali ketika Anda memulai shell baru. Ada batasan dalam hal itu jika Anda ingin menambahkan sesuatu yang sebelumnya (misalnya memindahkan jalur dalam $ PATH) atau sebaliknya, Anda harus melakukannya sendiri.sumber
$PATH
denganIFS=:
akhirnya lebih fleksibel daripadacase
.case
, IMO. Saya membayangkanawk
bisa dimanfaatkan dengan baik di sini juga.gawk
bisa langsung ditugaskan$PATH
.Anda bisa melakukannya dengan cara ini:
Catatan: jika Anda membuat PATH dari variabel lain, periksa apakah mereka tidak kosong, karena banyak shell mengartikan "" seperti "." .
sumber
-q
diperlukan oleh POSIX untuk grep, tapi saya tidak tahu apakah itu berarti masih ada beberapa (non POSIX) greps yang tidak memilikinya./my/bin
Bagian penting dari kode adalah untuk memeriksa apakah
PATH
mengandung jalur tertentu:Yaitu, pastikan bahwa setiap jalur di
PATH
dibatasi pada kedua sisi olehPATH
pemisah (:
), lalu periksa (-q
) apakah string literal (-F
) yang terdiri dariPATH
pemisah, jalur Anda, danPATH
pemisah lain ada di sana. Jika tidak, Anda dapat dengan aman menambahkan jalur:Ini harus kompatibel POSIX , dan harus bekerja dengan lintasan apa pun yang tidak mengandung karakter baris baru. Ini lebih kompleks jika Anda ingin bekerja dengan jalur yang berisi baris baru saat POSIX kompatibel, tetapi jika Anda memiliki
grep
yang mendukung-z
Anda dapat menggunakannya.sumber
Saya telah membawa fungsi kecil ini bersamaku di berbagai
~/.profile
file selama bertahun-tahun. Saya pikir itu ditulis oleh sysadmin di laboratorium tempat saya dulu bekerja tetapi saya tidak yakin. Bagaimanapun, ini mirip dengan pendekatan Goldilock tetapi sedikit berbeda:Jadi, untuk menambahkan direktori baru ke awal
PATH
:dan sampai akhir:
sumber
/bin/grep
->grep
MEMPERBARUI:
Saya perhatikan jawaban Anda sendiri memiliki fungsi terpisah masing-masing untuk menambahkan atau menambahkan ke
$PATH
. Saya menyukai ide itu. Jadi saya menambahkan sedikit penanganan argumen. Saya juga_
menempatkan nama dengan benar :KELUARAN:
Secara default ia akan
-A
membayar$PATH
, tetapi Anda dapat mengubah perilaku ini untuk-P
repend dengan menambahkan-P
di mana saja di daftar argumen Anda. Anda dapat mengubahnya kembali ke-A
ppending dengan menyerahkannya a-A
lagi.EVAL AMAN
Dalam kebanyakan kasus, saya menyarankan agar orang menghindari penggunaan
eval
. Tapi ini, saya pikir, menonjol sebagai contoh penggunaannya untuk kebaikan. Dalam hal ini satu-satunya pernyataan yangeval
bisa dilihat adalahP=
atauA=
. Nilai-nilai argumennya diuji secara ketat sebelum dipanggil. Ini untuk apaeval
.Ini akan menerima argumen sebanyak yang Anda berikan dan tambahkan masing-masing
$PATH
hanya satu kali dan hanya jika belum ada$PATH
. Itu menggunakan hanya shell-script POSIX sepenuhnya portabel, hanya bergantung pada built-in shell, dan sangat cepat.sumber
_
awalan fungsi shell membuat mereka "benar-benar diberi nama"? Dalam bahasa lain, biasanya akan menunjukkan fungsi global internal (yaitu, yang perlu global, tetapi tidak dimaksudkan untuk digunakan secara eksternal sebagai bagian dari API). Nama saya tentu saja bukan pilihan yang bagus, tetapi bagi saya sepertinya hanya menggunakan_
tidak menyelesaikan masalah tabrakan sama sekali - akan lebih baik untuk memakukan pada namespace yang sebenarnya, misalnya.mikeserv_path_assign()
._
maka Anda perlu mengganti manajer paket. Bagaimanapun, ini, pada dasarnya, hanyalah sebuah "global, internal, fungsi" - itu global untuk setiap shell yang dipanggil dari shell di mana ia dinyatakan, dan itu hanya sedikit naskah bahasa yang ditafsirkan nongkrong dalam memori juru bahasa . unix.stackexchange.com/questions/120528/…unset a
(atau yang setara) di akhir profil?Melihat! 12-line kekuatan-industri ... fungsi bash- dan zsh-portable shell yang secara khusus mencintai skrip startup
~/.bashrc
atau~/.zshrc
pilihan Anda:Persiapkan dirimu untuk kemuliaan sesaat. Kemudian, daripada melakukan ini dan berharap yang terbaik:
Lakukan ini sebagai gantinya dan dijamin mendapatkan yang terbaik, baik Anda benar-benar menginginkannya atau tidak:
Baiklah, Tentukan "Terbaik."
Aman menambahkan dan menambahkan ke arus
${PATH}
bukanlah masalah sepele seperti yang biasa terjadi. Sementara nyaman dan tampaknya masuk akal, one-liners formulirexport PATH=$PATH:~/opt/bin
mengundang komplikasi jahat dengan:Dirnames relatif tidak sengaja (misalnya,
export PATH=$PATH:opt/bin
). Sementarabash
danzsh
diam - diam menerima dan kebanyakan mengabaikan nama relatif dalam kebanyakan kasus, nama relatif relatif diawali oleh salah satuh
ataut
(dan mungkin karakter jahat lainnya) menyebabkan keduanya memutihkan diri mereka sendiri secara memalukan diri sendiri karya mahakaryanya pada tahun 1962 karya Masaki Kobayashi karya Harakiri :Duplikasi nama direktori secara tidak sengaja. Meskipun nama ganda duplikat
${PATH}
sebagian besar tidak berbahaya, mereka juga tidak diinginkan, rumit, sedikit tidak efisien, menghambat debuggability, dan mempromosikan drive wear - agak seperti jawaban ini. Sementara SSD gaya NAND ( tentu saja ) kebal terhadap keausan baca, HDD tidak. Akses sistem file yang tidak perlu pada setiap perintah yang dicoba menyiratkan keausan baca yang tidak perlu pada tempo yang sama. Duplikat khususnya tidak berbahaya ketika menggunakan cangkang bersarang di subproses bersarang, di mana titik yang tampaknya tidak berbahaya satu-garis sepertiexport PATH=$PATH:~/wat
dengan cepat meledak ke dalam Lingkaran${PATH}
Neraka Ke Tujuh sepertiPATH=/usr/local/bin:/usr/bin:/bin:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat
. Hanya Beelzebubba yang dapat membantu Anda jika Anda kemudian menambahkan nama pengguna tambahan ke dalamnya. (Jangan biarkan ini terjadi pada anak-anakmu yang berharga. )${PATH}
sebagian besar tidak berbahaya, mereka juga biasanya tidak diinginkan, rumit, sedikit tidak efisien, menghambat debuggability, dan mempromosikan drive wear.Ergo, otomatisasi ramah seperti fungsi shell yang didefinisikan di atas. Kita harus menyelamatkan diri kita sendiri.
Tapi ... Kenapa "+ path.append ()"? Kenapa Tidak Cukup append_path ()?
Untuk disambiguitas (misalnya, dengan perintah eksternal dalam
${PATH}
fungsi shell saat ini atau di seluruh sistem yang didefinisikan di tempat lain), fungsi shell yang ditentukan pengguna idealnya diawali atau diakhiri dengan substring unik yang didukung olehbash
danzsh
tetapi sebaliknya dilarang untuk nama-nama perintah standar - seperti, misalnya+
,.Hei. Berhasil. Jangan menilai saya.
Tapi ... Kenapa "+ path.append ()"? Mengapa Tidak "+ path.prepend ()"?
Karena menambahkan ke arus
${PATH}
lebih aman daripada bergantung pada arus${PATH}
, semua hal dianggap sama, yang tidak pernah ada. Mengganti perintah di seluruh sistem dengan perintah khusus pengguna dapat menjadi tidak bersih paling baik dan paling tidak membuat gila. Di Linux, misalnya, aplikasi hilir umumnya mengharapkan varian perintah GNU coreutils daripada turunan atau alternatif non-standar khusus.Yang mengatakan, benar-benar ada kasus penggunaan yang valid untuk melakukannya. Menentukan
+path.prepend()
fungsi yang setara itu sepele. Sans prolix nebulosity, untuk kewarasannya bersama:Tapi ... Kenapa Tidak Gilles?
Gilles ' jawaban diterima di tempat lain optimal mengesankan dalam kasus umum sebagai 'shell agnostik idempoten append' . Dalam kasus umum
bash
danzsh
dengan tidak ada symlink yang tidak diinginkan, bagaimanapun, hukuman kinerja yang diperlukan untuk melakukannya sedih yang ricer Gentoo dalam diriku. Bahkan di hadapan symlink yang tidak diinginkan, masih diperdebatkan apakah forking satu subshell peradd_to_PATH()
argumen bernilai potensi penyisipan duplikat symlink.Untuk kasus penggunaan yang ketat yang menuntut duplikat symlink dihilangkan,
zsh
varian khusus ini melakukannya melalui builtin yang efisien dan bukannya garpu yang tidak efisien:Perhatikan
*":${dirname:A}:"*
bukan*":${dirname}:"*
yang asli.:A
adalahzsh
-ism yang luar biasa sayangnya tidak ada di bawah sebagian besar kerang lainnya - termasukbash
. Mengutipman zshexpn
:Tidak ada pertanyaan lebih lanjut.
Sama-sama. Nikmati penembakan yang aman. Anda sekarang layak menerimanya.
sumber
Ini versi fungsional-gaya pemrograman saya.
*PATH
variabel yang dibatasi oleh titik dua , tidak hanyaPATH
.Juga patut diperhatikan:
export
ing; yang tersisa untuk penelepon (lihat contoh)bash
; tidak bercabangsumber
Script ini memungkinkan Anda untuk menambahkan di akhir
$PATH
:Atau tambahkan di awal
$PATH
:sumber