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

Мне интересно, где новый путь должен быть добавлен в переменную среды PATH. Я знаю, что это может быть выполнено путем редактирования .bashrc (например), но неясно, как это сделать.

Таким образом:

 export PATH=~/opt/bin:$PATH

или это?

export PATH=$PATH:~/opt/bin
737 голосов | спросил Paolo 5 MonEurope/Moscow2011-12-05T00:57:14+04:00Europe/Moscow12bEurope/MoscowMon, 05 Dec 2011 00:57:14 +0400 2011, 00:57:14

11 ответов


806

Простой материал

PATH=$PATH:~/opt/bin
PATH=~/opt/bin:$PATH

в зависимости от того, хотите ли вы добавить в конец код ~/opt/bin (для поиска по всем другим каталогам, если есть программа с тем же именем в нескольких каталогах) или в начало (для поиска перед всеми другими каталогами).

Вы можете добавить несколько записей одновременно. PATH=$PATH:~/opt/bin:~/opt/node/bin или изменения в порядке упорядочения просто отлично.

Вам не нужно export, если переменная уже находится в среде: любое изменение значения переменной отражается в среде .¹ PATH довольно много всегда в окружающей среде; все системы unix устанавливают его очень рано (обычно в самом первом процессе, фактически).

Если ваш PATH создается многими разными компонентами, вы можете получить дубликаты записей. См. Как добавить путь к домашней директории, который будет обнаружен Unix, который команду? и Удалите повторяющиеся записи $ PATH с помощью команды awk , чтобы избежать дублирования или удалить их.

Где поставить

Обратите внимание, что ~/.bash_rc не читается какой-либо программой, а ~/.bashrc - это файл конфигурации интерактивных экземпляров bash. Вы не должны определять переменные среды в ~/.bashrc. Правильное место для определения переменных среды, таких как PATH, это ~/.profile (или ~/.bash_profile, если вам не нравятся оболочки кроме bash). См. В чем разница между ними и какой из них я должен использовать?

Заметки о оболочках, отличных от bash

В bash, ksh и zsh, export - специальный синтаксис, и оба PATH=~/opt/bin:$PATH и export PATH=~/opt/bin:$PATH делать правильные вещи даже. В других оболочках Bourne /POSIX, таких как тире (который является /bin/sh на многих системах), export анализируется как обычная команда, что подразумевает две отличия:

Итак, в оболочках, таких как тире, export PATH=~/opt/bin:$PATH устанавливает PATH в литеральную строку ~/opt/bin/:, за которым следует значение PATH до первого места. PATH=~/opt/bin:$PATH (простое назначение) не требует кавычек и делает все правильно. Если вы хотите использовать export в переносном скрипте, вам нужно написать export PATH="$HOME/opt/bin:$PATH" или PATH=~/opt/bin:$PATH export PATH (или PATH=$HOME/opt/bin:$PATH export PATH для переносимости даже для оболочки Bourne, которая не принимает export var=value и не делал расширения тильды).

¹ Это было неверно в оболочках Bourne (как в реальной оболочке Bourne, а не в современных оболочках в стиле POSIX), но вы вряд ли столкнетесь с такими старыми оболочками в наши дни. Суб>

ответил Gilles 5 MonEurope/Moscow2011-12-05T03:39:48+04:00Europe/Moscow12bEurope/MoscowMon, 05 Dec 2011 03:39:48 +0400 2011, 03:39:48
72

В любом случае работает, но они не делают то же самое: элементы PATH проверяются слева направо. В первом примере исполняемые файлы в ~/opt/bin будут иметь приоритет над установленными, например, в /usr/bin, что может быть или не быть тем, что вы хотите.

В частности, с точки зрения безопасности опасно добавлять пути к фронту, потому что, если кто-то может получить доступ на запись к вашему ~/opt/bin, они могут поместить для например, другой ls, который вы, вероятно, будете использовать вместо /bin/ls, не заметив. Теперь представьте себе то же самое для ssh или вашего браузера или выбора ... (То же самое в три раза поместить на ваш путь.)

ответил Ulrich Schwarz 5 MonEurope/Moscow2011-12-05T01:09:46+04:00Europe/Moscow12bEurope/MoscowMon, 05 Dec 2011 01:09:46 +0400 2011, 01:09:46
32

Я запутался в вопросе 2 (поскольку он удален из вопроса, поскольку он был связан с не связанной проблемой):

  

Каков эффективный способ добавления дополнительных путей в разные строки?   Первоначально я думал, что это может сделать трюк:

     
export PATH=$PATH:~/opt/bin
export PATH=$PATH:~/opt/node/bin
     

, но это не потому, что второе назначение не только добавляет   ~/opt/node/bin, но также назначенный ранее PATH.

     

Это возможное обходное решение:

     
export PATH=$PATH:~/opt/bin:~/opt/node/bin
     

, но для удобства чтения я предпочел бы иметь одно назначение для одного пути.

Если вы скажете

PATH=~/opt/bin

это all , которое будет в вашем PATH. PATH - это просто переменная среды, и если вы хотите добавить в PATH, вам нужно перестроить переменную именно с нужным содержимым. То есть то, что вы даете в качестве примера на вопрос 2, - это именно то, что вы хотите сделать, если я не полностью упустил точку вопроса.

Я использую обе формы в своем коде. У меня есть общий профиль, который я устанавливаю на каждую машину, на которой я работаю, которая выглядит так: для размещения потенциально пропавших каталогов:

export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11
# add optional items to the path
for bindir in $HOME/local/bin $HOME/bin; do
    if [ -d $bindir ]; then
        PATH=$PATH:${bindir}
    fi
done
ответил Carl Cravens 5 MonEurope/Moscow2011-12-05T04:25:26+04:00Europe/Moscow12bEurope/MoscowMon, 05 Dec 2011 04:25:26 +0400 2011, 04:25:26
21

Linux определяет исполняемый путь поиска с переменной окружения $PATH. Чтобы добавить каталог /данные /myscripts в начало переменной окружения $PATH, используйте следующее:

PATH=/data/myscripts:$PATH

Чтобы добавить этот каталог в конец пути, используйте следующую команду:

PATH=$PATH:/data/myscripts

Но предыдущие недостаточно, потому что, когда вы устанавливаете переменную среды внутри скрипта, это изменение действует только внутри скрипта. Это ограничение ограничено двумя способами:

  • Если внутри скрипта вы экспортируете переменную окружения, она эффективна в рамках любых программ, вызываемых скриптом. Обратите внимание, что это не эффективно в программе, которая вызвала сценарий.
  • Если программа, вызывающая сценарий, делает это путем включения вместо вызова, любые изменения среды в скрипте эффективны в вызывающей программе. Такое включение может быть выполнено с помощью команды dot или исходной команды.

Примеры:

$HOME/myscript.sh
source $HOME/myscript.sh

Включение в основном включает «вызываемый» скрипт в сценарии «вызова». Это похоже на #include в C. Таким образом, он эффективен внутри скрипта или программы вызова. Но, конечно, это не эффективно для любых программ или скриптов, вызываемых вызывающей программой. Чтобы сделать его эффективным вплоть до цепочки вызовов, вы должны следовать настройке переменной среды с помощью команды export.

В качестве примера, программа оболочки bash включает в себя содержимое файла .bash_profile по включению. Итак, поместите следующие 2 строки в .bash_profile:

PATH=$PATH:/data/myscripts
export PATH

эффективно помещает эти 2 строки кода в программу bash. Таким образом, в bash переменная $ PATH включает $HOME/myscript.sh, и из-за инструкции экспорта любые программы, вызываемые bash, имеют измененную переменную $PATH. И поскольку любые программы, которые вы запускаете из приглашения bash, вызываются bash, новый путь действует для всего, что вы запускаете из приглашения bash.

Суть в том, что для добавления нового каталога в путь вам необходимо добавить или добавить каталог в переменную среды $ PATH в скрипте, включенном в оболочку, и вы должны экспортировать $PATH переменная среды.

Дополнительная информация здесь

ответил Steve Brown 5 MonEurope/Moscow2011-12-05T04:31:58+04:00Europe/Moscow12bEurope/MoscowMon, 05 Dec 2011 04:31:58 +0400 2011, 04:31:58
17

В течение некоторого времени я сохранил со мной две функции pathadd и pathrm, которые помогают добавлять элементы в путь, не беспокоясь о дублированиях.

pathadd принимает один аргумент пути и необязательный аргумент after, который, если он будет добавлен, добавится к PATH, иначе он добавит его.

В любой ситуации, если вы добавляете путь, вы, вероятно, хотите переопределить все, что уже есть в пути, поэтому я предпочитаю добавлять по умолчанию.

pathadd() {
    newelement=${1%/}
    if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then
        if [ "$2" = "after" ] ; then
            PATH="$PATH:$newelement"
        else
            PATH="$newelement:$PATH"
        fi
    fi
}

pathrm() {
    PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}

Поместите их в любой скрипт, который вы хотите изменить среду PATH, и теперь вы можете сделать.

pathadd "/foo/bar"
pathadd "/baz/bat" after
export PATH

Вам гарантировано не добавлять путь, если он уже существует. Если вы хотите, чтобы в начале был запущен /baz/bat.

pathrm "/baz/bat"
pathadd "/baz/bat"
export PATH

Теперь любой путь можно перемещать на передний план, если он уже находится на пути без удвоения.

ответил Brett Ryan 18 MaramFri, 18 Mar 2016 02:28:51 +03002016-03-18T02:28:51+03:0002 2016, 02:28:51
10

Пуленепробиваемый способ добавления /предварительной подготовки

Существует множество соображений, связанных с выбором добавления и добавления. Многие из них описаны в других ответах, поэтому я не буду повторять их здесь.

Важным моментом является то, что даже если системные скрипты не используют это (интересно, почему) * 1 , пуленепробиваемый способ добавления пути (например, $HOME/bin) к переменной среды PATH

PATH="${PATH:+${PATH}:}$HOME/bin"

для добавления (вместо PATH="$PATH:$HOME/bin") и

PATH="$HOME/bin${PATH:+:${PATH}}"

для добавления (вместо PATH="$HOME/bin:$PATH")

Это позволяет избежать ложного ведущего /конечного двоеточия, когда $PATH изначально пуст, что может иметь нежелательные побочные эффекты и может стать кошмаром , неуловимо найти ( этот ответ вкратце рассматривает случай awk -way).

Объяснение (из Расширение параметров оболочки ):

${parameter:+word}
     

Если параметр parameter имеет значение null или unset, ничего не заменяется, в противном случае заменяется слово word.

Таким образом, ${PATH:+${PATH}:} расширяется до: 1) ничего, если PATH имеет значение null или unset, 2) ${PATH}:, если установлен PATH.

Примечание . Это для bash.


* 1 Я только что нашел, что скрипты вроде devtoolset-6/enable действительно используют это,
$ cat /opt/rh/devtoolset-6/enable
# General environment variables
export PATH=/opt/rh/devtoolset-6/root/usr/bin${PATH:+:${PATH}}
...
ответил sancho.s 5 Jpm1000000pmFri, 05 Jan 2018 19:36:14 +030018 2018, 19:36:14
9

Я не могу говорить для других дистрибутивов, но у Ubuntu есть файл, /etc /environment, который является стандартным поисковым путем для всех пользователей. Поскольку мой компьютер используется только мной, я помещаю любые каталоги, которые я хочу на свой путь там, если это не временное дополнение, которое я ввел в скрипт.

ответил Jim Bradley 7 FebruaryEurope/MoscowbSat, 07 Feb 2015 08:17:26 +0300000000amSat, 07 Feb 2015 08:17:26 +030015 2015, 08:17:26
5

Вот мое решение:

PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

Хороший легкий один вкладыш, который не оставляет завершающего :

ответил AJ. 29 MonEurope/Moscow2014-12-29T10:12:24+03:00Europe/Moscow12bEurope/MoscowMon, 29 Dec 2014 10:12:24 +0300 2014, 10:12:24
4

Для меня (в Mac OS X 10.9.5) добавление имени пути (например, /mypathname) в файл /etc/paths работало очень хорошо.

Перед редактированием возвращается echo $PATH:

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

После редактирования /etc/paths и перезапуска оболочки переменная $ PATH добавляется с помощью /pathname. Действительно, echo $PATH возвращает:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname

Случилось так, что /mypathname был добавлен в переменную $PATH.

ответил faelx 27 +03002015-10-27T18:01:05+03:00312015bEurope/MoscowTue, 27 Oct 2015 18:01:05 +0300 2015, 18:01:05
2

Чтобы добавить новый путь к переменной окружения PATH:

export PATH=$PATH:/new-path/

Чтобы это изменение применимо к каждой открытой оболочке, добавьте ее в файл, в котором оболочка будет source при вызове. В разных оболочках это может быть:

  • Bash Shell: ~ /.bash_profile, ~ /.bashrc или профиль
  • Korn Shell: ~ /.kshrc или .profile
  • Z Shell: ~ /.zshrc или .zprofile

например.

# export PATH=$PATH:/root/learning/bin/
# source ~/.bashrc
# echo $PATH

Вы можете видеть предоставленный путь в вышеприведенном выходе.

ответил Amit24x7 12 J0000006Europe/Moscow 2017, 13:47:42
1

Есть несколько ситуаций, когда использование PATH=/a/b:$PATH может считаться «неправильным» способом добавления пути к PATH:

  1. Добавление пути, который на самом деле не является каталогом.
  2. Добавление пути, который уже находится в PATH в той же форме.
  3. Добавление относительного пути (поскольку текущий поиск каталога будет меняться при изменении текущего рабочего каталога).
  4. Добавление пути, который уже находится в PATH, в другой форме (т. е. псевдоним из-за использования символических ссылок или ..).
  5. Если вы избегаете делать 4, не перемещая путь к началу PATH, когда он предназначен для переопределения других записей в PATH.

Эта функция (только Bash-only) выполняет «правильную вещь» в приведенных выше ситуациях (с исключением, см. ниже), возвращает коды ошибок и печатает хорошие сообщения для людей. Коды ошибок и сообщения могут быть отключены, когда они не нужны.

prepath() {
    local usage="\
Usage: prepath [-f] [-n] [-q] DIR
  -f Force dir to front of path even if already in path
  -n Nonexistent dirs do not return error status
  -q Quiet mode"

    local tofront=false errcode=1 qecho=echo
    while true; do case "$1" in
        -f)     tofront=true;       shift;;
        -n)     errcode=0;          shift;;
        -q)     qecho=':';          shift;;
        *)      break;;
    esac; done
    # Bad params always produce message and error code
    [[ -z $1 ]] && { echo 1>&2 "$usage"; return 1; }

    [[ -d $1 ]] || { $qecho 1>&2 "$1 is not a directory."; return $errcode; }
    dir="$(command cd "$1"; pwd -P)"
    if [[ :$PATH: =~ :$dir: ]]; then
        $tofront || { $qecho 1>&2 "$dir already in path."; return 0; }
        PATH="${PATH#$dir:}"        # remove if at start
        PATH="${PATH%:$dir}"        # remove if at end
        PATH="${PATH//:$dir:/:}"    # remove if in middle
    fi
    PATH="$dir:$PATH"
}

Исключением является то, что эта функция не канонизирует пути, добавленные к PATH, с помощью других средств, поэтому, если неканонический псевдоним для пути находится в PATH, это будет добавьте дубликат. Попытка канонизировать пути уже в PATH - это рискованное предложение, поскольку относительный путь имеет очевидное значение при передаче в prepath, но когда уже на пути вы не знаете, что текущий рабочий каталог был, когда он был добавлен.

ответил Curt J. Sampson 2 42017vEurope/Moscow11bEurope/MoscowThu, 02 Nov 2017 06:30:06 +0300 2017, 06:30:06

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132