Menambahkan jalur ke PATH menggunakan sintaksis multi-baris

16

Sejauh yang saya mengerti, cara biasa untuk menambahkan path ke PATHvariabel lingkungan adalah dengan menyatukan path yang dipisahkan oleh :karakter.

Misalnya, jika saya ingin menambahkan tiga jalur ke sana /my/path/1, /my/path/2dan /my/path/3, saya harus melakukannya sebagai berikut:

PATH=$PATH:/my/path/1:/my/path/2:/my/path/3

yang tidak mudah dibaca.

Apakah ada cara untuk mendefinisikan atau menambahkan path ke PATHvariabel menggunakan sintaksis multi-line ? Mungkin menggunakan array? Saya mencari sesuatu seperti ini:

PATH = 
$PATH
/my/path/1
/my/path/2
/my/path/3

Jika ada solusi menarik yang spesifik untuk shell, saya mencari solusi di zsh.

Amelio Vazquez-Reina
sumber

Jawaban:

12

Saya tidak tahu apakah itu berfungsi di zsh, tetapi bekerja di bash:

PATH=$(paste -d ":" -s << EOF 
$PATH
/my/path/1
/my/path/2
/my/path/3
EOF
)

Edit dan bahkan lebih pendek:

PATH=`paste -d ":" -s << EOF 
$PATH
/my/path/1
/my/path/2
/my/path/3
EOF`

Dan tanpa memunculkan proses:

new_path=(
"$PATH"
/my/path/1
/my/path/2
/my/path/3)
OLD_IFS="$IFS"
export IFS=":"
PATH="${new_path[*]}"
export IFS="$OLD_IFS"

Tanda kutip ganda diseluruh penting $PATH, $IFS, ${new_path[*]}dan $OLD_IFSuntuk menjaga ruang dalam penafsiran variabel dan menghindari shell dari IFS.

Update2 dengan komentar dan manajemen baris kosong menggunakan sed:

PATH=`sed -e '/^#/'d -e '/^$/'d << EOF | paste -d ":" -s 
$PATH
/my/path/1
# This is a comment.
/my/path/2

/my/path/3
EOF`

Karakter komentar harus menjadi karakter pertama di baris, dan baris kosong harus benar-benar kosong. Untuk mengelola spasi dan tab sebelum komentar dan pada baris kosong, gunakan sed -e '/^[ \t]*#/'d -e '/^[ \t]*$/'dsebagai gantinya (tab yang akan diuji karena mungkin spesifik untuk implementasi sed).

jfg956
sumber
Saya menguji cuplikan terakhir di zsh dan berhasil. Saya juga suka itu sedikit lebih bersih (satu jalur per baris) daripada solusi lainnya. Bisakah solusi mengakomodasi garis (jalur) yang dikomentari? Bagaimana dengan baris kosong?
Amelio Vazquez-Reina
Perbarui dengan komentar dan manajemen baris kosong.
jfg956
Dan dengan sed, jika Anda ingin bermain, Anda dapat menghindari proses tempel dengan skrip yang lebih rumit.
jfg956
Apakah boleh menggunakan lekukan untuk jalur dalam pastesolusi?
void.pointer
20

Sama sekali bukan solusi yang menarik, tetapi sangat portabel:

PATH=${PATH}:/my/path/1
PATH=${PATH}:/my/path/2
PATH=${PATH}:/my/path/3
Tikar
sumber
1
Ini khas dari apa yang saya lihat selama bertahun-tahun. Seseorang dapat dengan mudah menyusun ulang lintasan atau bahkan mengubah elemen menjadi PATH = / my / path / 1: $ {PATH} untuk memaksa prepending.
bsd
1
Anda juga dapat menggunakannya +=untuk menghindari keharusan membangun kembali string sepenuhnya.
Chris Down
Dan Anda bahkan tidak perlu menggunakan kawat gigi. Titik dua tidak dapat digunakan dalam nama variabel lingkungan sehingga tidak ada ambiguitas untuk diselesaikan.
Alexios
+1 karena tidak menarik. Kadang-kadang memang menarik, tapi kali ini tidak! (Terutama karena OP secara eksplisit menyebut "tidak mudah dibaca" sebagai masalah.)
ruakh
@ ChrisDown Apakah ada sintaks yang menambahkan tanpa membangun kembali string?
John P
12

Di zsh, $pathadalah array:

path=(
    $path
    ~/.local/bin
    ~/.gem/ruby/2.0.0/bin
)

Catatan: keduanya pathhuruf kecil.

Kabie
sumber
Itu tergantung pada shell, tidak semua menangani ini.
vonbrand
1
@vonbrand: Ya, Tapi berfungsi di zsh. Saya pikir itu layak untuk disebutkan.
Kabie
3
+1 (Pertanyaan ini ditandai zsh )
Johnsyweb
Karena OP secara khusus bertanya tentang zsh, ini adalah opsi terbaik
Daniel Serodio
1
bagi siapa pun yang tertarik untuk mempelajari lebih lanjut tentang perbedaan $ path vs. $ PATH, lihat pos ini
mbigras
7

Di zsh, jika Anda menambahkan direktori di ujung jalan:

path+=/my/path/1
path+=/my/path/2
path+=(/path/to/app/{i386,share}/bin)

Portable: Bagaimana cara menambahkan path ke PATH dengan benar?

Anda dapat menggunakan kualifikasi glob untuk mengecualikan entri yang tidak ada direktori atau tautan simbolis ke sana. Ini mungkin atau mungkin tidak diinginkan, tergantung pada apakah Anda mengharapkan direktori akan ditambahkan kemudian selama sesi (misalnya jika mereka berada di sistem file jarak jauh). Anda tidak dapat melakukannya dengan path+=/my/pathsintaks karena sisi kanan berada dalam konteks string dan tidak mengalami globbing; Anda dapat melakukannya dengan path+=(/my/path)karena setiap elemen array diperluas dalam konteks daftar.

path+=(/path/to/app/{i386,share}/bin(-/N))
Gilles 'SANGAT berhenti menjadi jahat'
sumber