Добавление путей в PATH с использованием многострочного синтаксиса

16

Насколько я понимаю, обычным способом добавления пути к PATHпеременной среды является объединение путей, разделенных :символом.

Например, если я хочу добавить к нему три пути /my/path/1, /my/path/2и /my/path/3я должен сделать это следующим образом:

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

который не легко читать.

Есть ли способ определить или добавить пути к PATHпеременной, используя многострочный синтаксис ? Возможно, используя массивы? Я ищу что-то вроде этого:

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

Если есть интересные решения, относящиеся к конкретной оболочке, я ищу решение в zsh.

Амелио Васкес-Рейна
источник

Ответы:

12

Я не знаю, работает ли он в zsh, но работает в bash:

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

Редактировать и еще короче:

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

И без порождения процесса:

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

Двойные кавычки необходимы Arround $PATH, $IFS, ${new_path[*]}и $OLD_IFSсохранить пробелы в интерпретации переменных и избежать оболочечной МФС.

Update2 с комментариями и управлением пустой строкой с использованием 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`

Символ комментария должен быть первым символом в строке, а пустые строки должны быть полностью пустыми. Для управления пробелами и вкладками перед комментарием и пустыми строками используйте sed -e '/^[ \t]*#/'d -e '/^[ \t]*$/'dвместо этого (тестируемые вкладки, поскольку они могут быть специфическими для реализации sed).

jfg956
источник
Я протестировал последний фрагмент в Zsh, и он работает. Мне также нравится, что это немного чище (один путь на строку), чем другие решения. Может ли решение вместить закомментированные строки (пути)? Как насчет пустых строк?
Амелио Васкес-Рейна
Обновление с комментариями и пустой строкой управления.
jfg956
А с помощью sed, если вы хотите играть, вы можете избежать процесса вставки с помощью более сложного сценария.
jfg956
Можно ли использовать отступ для путей в pasteрешении?
void.pointer
20

Совсем не интересное решение, но очень портативное:

PATH=${PATH}:/my/path/1
PATH=${PATH}:/my/path/2
PATH=${PATH}:/my/path/3
Мат
источник
1
Это типично для того, что я видел за эти годы. Можно легко изменить порядок путей или даже изменить элемент на PATH = / my / path / 1: $ {PATH} для принудительного добавления.
BSD
1
Вы также можете использовать, +=чтобы избежать необходимости полностью перестроить строку.
Крис Даун
И вам даже не нужно использовать брекеты. Двоеточия нельзя использовать в именах переменных среды, поэтому нет никакой неоднозначности для разрешения.
Алексиос
+1 за неинтересность. Иногда может быть интересно, но это не один из тех моментов! (Тем более, что в ОП явно упоминается «не легко читать» как проблему.)
ruakh
@ChrisDown Есть ли синтаксис, который добавляется без перестройки строки?
Джон П,
12

В zsh $pathесть массив:

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

Примечание: оба pathв нижнем регистре.

Kabie
источник
Это зависит от оболочки, не все справляются с этим.
vonbrand
1
@ Vonbrand: Да, но работает в Zsh. Я думаю, что стоит упомянуть.
Каби
3
+1 (Этот вопрос помечен zsh )
Johnsyweb
Так как ОП специально спрашивал про zsh, это лучший вариант
Даниэль Серодио
1
Для тех, кто хочет узнать больше о различиях $ path и $ PATH, ознакомьтесь с этим постом
mbigras
7

В zsh, если вы добавляете каталоги в конце пути:

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

Портабельно: Как правильно добавить путь к PATH?

Вы можете использовать квалификаторы glob для исключения записей, которые не являются существующими каталогами или символическими ссылками на них. Это может или не может быть желательным, в зависимости от того, ожидаете ли вы, что каталоги могут быть добавлены позже во время сеанса (например, если они находятся на удаленных файловых системах). Вы не можете сделать это с помощью path+=/my/pathсинтаксиса, потому что правая часть находится в строковом контексте и поэтому не подвергается глобализации; Вы можете сделать это, path+=(/my/path)поскольку каждый элемент массива раскрывается в контексте списка.

path+=(/path/to/app/{i386,share}/bin(-/N))
Жиль "ТАК - перестань быть злым"
источник