Удалите лишние пути из переменной $ PATH

125

Я 6 раз определял один и тот же путь в переменной $ PATH.

Я не выходил из системы, чтобы проверить, работает ли это.

Как удалить дубликаты?

Переменная $ PATH выглядит так:

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

Как мне сбросить его на

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
Чарльз Хендри
источник
где ты это 6 раз определял? в каких файлах?
hovanessyan
3
возможный дубликат. Какой самый элегантный способ удалить путь из переменной $ PATH в Bash?
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Ответы:

122

Вы просто выполняете:

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

это будет для текущего сеанса, если вы хотите изменить навсегда, добавьте его в любой .bashrc, bash.bashrc, / etc / profile - все, что подходит вашей системе и потребностям пользователя.

Примечание: это для Linux. Мы проясним это для начинающих программистов. (`, ') Не пытайтесь установить = this.

hovanessyan
источник
да, я установил их постоянно в bash.bashrc. Так должна ли команда быть примерно такой? echo 'export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' >> ~/.bashrc
charles hendry
дело в том, что в зависимости от вашей ОС выполняется цепочка конфигураций. Вам нужно убедиться, что переменная PATH не будет перезаписана позже. Самый простой способ сделать это (для одного пользователя) - перезаписать его в личном .bashrc пользователя, который обычно находится в его домашнем каталоге.
ованесян
1
ваша команда устанавливает PATH равным - $ PATH (текущее значение PATH) + строка / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / USR / гам эс. Если вы хотите иметь только строку, удалите из команды $ PATH + точку с запятой (:). Неважно, используете ли вы echo или редактируете файл ~ / .bashrc вручную.
ованесян
файл bash.bashrc находится в папке / etc. Однако он не отображает переменную $ PATH, поэтому я не уверен, где ее редактировать
Чарльз Хендри
в своем первом комментарии вы откликаетесь на ~ / .bashrc (цитируется: >> ~ / .bashrc), а не на /etc/bash.bashrc. Если вы хотите изменить ПУТЬ для конкретного пользователя, отредактируйте его в / home / <имя пользователя> / .bashrc файле. /etc/bash.bashrc применяется ко всем пользователям.
ованесян
70

Если вы используете Bash, вы также можете сделать следующее, если, скажем, вы хотите удалить каталог /home/wrong/dir/из своей PATHпеременной:

PATH=`echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'`
sufinawaz
источник
1
Это было полезно для меня, так как в / etc / profile был добавлен каталог, который я хотел исключить, но у меня нет доступа на запись в / etc. Спасибо :)
Samizdis
13
Совет: вы можете использовать другой разделитель в выражении sed, чтобы избежать экранирования \ /:PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||')
iNecas
4
Этот трюк помогает, когда я хочу сразу же получить новый PATH и не хочу выходить из текущего терминала. Однако, чтобы избежать путаницы, следует поэкспериментировать с командой генерации PATH (т.е. echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//') перед назначением ее переменной PATH.
биокибермэн
2
Это не сработает, если удаляемый путь является первым путем в $PATH. Используйте это:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//')
Робин Сю,
не работает $ PATH=echo $ PATH | sed -e 's /: \ / scratch \ / sjn \ / anaconda \ / bin \ / python \ / $ //' 'для удаления / scratch / sjn / anaconda / bin / python
Мона Джалал,
13

Linux: удалить избыточные пути из переменной $ PATH

Linux From Scratch имеет эту функцию в / 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"
}

Это предназначено для использования с этими функциями для добавления к пути, чтобы вы не делали это повторно:

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

Простое использование - просто указать pathremoveпуть к каталогу для удаления, но имейте в виду, что он должен точно совпадать:

$ pathremove /home/username/anaconda3/bin

Это удалит каждый экземпляр этого каталога из вашего пути.

Если вам нужен каталог на вашем пути, но без дублирования, вы можете просто использовать одну из других функций, например - для вашего конкретного случая:

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

Но, если удобочитаемость не является проблемой, на этом этапе вам лучше просто сделать:

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

Будет ли это работать во всех известных человеку оболочках?

Я полагаю , выше , чтобы работать в sh, dashи , по bashкрайней мере. Я был бы удивлен, узнав, что это не работает csh, fish', orкш. Я сомневаюсь, что это будет работать в командной оболочке Windows или Powershell.

Если у вас есть Python, следующая команда должна делать то, что вам прямо запрошено (то есть удалять избыточные пути):

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

Однострочный (чтобы обойти многострочные проблемы):

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

Вышесказанное удаляет более поздние избыточные пути. Чтобы удалить более ранние избыточные пути, используйте индекс перевернутого списка и снова переверните его:

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')[::-1]
print(':'.join(sorted(set(path), key=path.index, reverse=True)))
" )
Аарон Холл
источник
+1. работает ли pathremove () во всех вариантах оболочки, например, csh, ksh, bash и т. д.? кстати, мой / etc / profile на RHEL не имеет partremove (), но имеет только pathmunge ().
Tagar
1
@Tagar Я не даю никаких гарантий относительно совместимости со всеми остальными оболочками. Я предлагаю протестировать его на любой оболочке, которую вы используете, и если она не работает для вашей оболочки, вы можете использовать Python, если он у вас установлен - я добавил немного Python в ответ, чтобы описать, как.
Аарон Холл
Если я правильно прочитал «3.5.3 Расширение параметров оболочки», ${!PATHVARIABLE}это своего рода косвенное обращение к переменной, но я не уверен, как это работает здесь. Не могли бы вы объяснить это, пожалуйста?
loxaxs 01
@loxaxs Это локальная переменная в этих функциях bash, объявленная с помощью localвстроенной функции (которая может использоваться только внутри функции). Если у вас есть дополнительные вопросы, вам, вероятно, следует задать новый вопрос на сайте (предварительно выполнив поиск, чтобы убедиться, что вы не создаете точную копию ...).
Аарон Холл
Это действительно интересный ответ, спасибо за отзыв! Однако исходный вопрос об очистке испорченной переменной PATH, похоже, не решен изящно (хотя, я признаю, тогда при использовании этих функций можно не получить испорченный PATH для начала).
Christian Herenz
9

Вот однострочный код, который очищает PATH

  • Это не нарушает порядок PATH, просто удаляет дубликаты
  • Лечит: и изящно опорожняет PATH
  • Никаких специальных символов не используется, поэтому не требуется escape
  • Используется /bin/awkтак, чтобы он работал, даже когда PATH не работает

    export PATH="$(echo "$PATH" |/bin/awk 'BEGIN{RS=":";}
    {sub(sprintf("%c$",10),"");if(A[$0]){}else{A[$0]=1;
    printf(((NR==1)?"":":")$0)}}')";
    
Greenfox
источник
1
кто нибудь тестировал? безопасно?
Joe RR
2
если у вас не установлен awk, он очищает ваш путь, я советую скопировать ваш путь к txt файлу раньше с помощью echo $ PATH
Jose Pita
У меня не работает ... У меня установлен awk, но некоторые дубликаты не удаляются.
Christian Herenz
3
  1. Просто echo $PATH
  2. копировать детали в текстовый редактор
  3. удалить ненужные записи
  4. PATH= # pass new list of entries
mrwagaba
источник
2

Если вы просто хотите удалить любые повторяющиеся пути, я использую этот сценарий, который написал некоторое время назад, так как у меня были проблемы с несколькими путями 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"

И я помещаю его в свой ~ / .profile в конце. Поскольку я использую почти исключительно BASH, я не пробовал его в других оболочках.

Кевин Натан
источник
1
+1 за решение. Кстати, он удалит дублирующиеся пути только в том случае, если они идут в списке один за другим. Вы можете изменить |uniqна, |sort|uniqчтобы исправить это, но это изменит порядок всех каталогов в пути, что я не считаю желаемым побочным эффектом.
Tagar
1

Предполагая, что ваша оболочка - Bash, вы можете установить путь с помощью

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

но, как сказал Левон в другом ответе, как только вы завершите оболочку, изменения исчезнут. Вы, вероятно, захотите настроить свой PATHin ~/.bash_profileили ~/.bashrc.

Лео
источник
1

В bash вы можете просто $ {var / find / replace}

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

Или в этом случае (поскольку бит замены пуст) просто:

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

Я пришел сюда первым, но пошел еще дальше, так как думал, что для этого потребуется расширение параметров . Легче, чем sed !.

Как заменить символ или слово-заполнитель в переменной значением из другой переменной в Bash?

sabgenton
источник
%означает совпадение, если в конце строки, то #в начале.
Sabgenton
0

Не существует стандартных инструментов для «редактирования» значения $PATH(например, «добавлять папку, только если она еще не существует» или «удалять эту папку»).

Чтобы проверить, каким будет путь при следующем входе в систему, используйте telnet localhost(или telnet 127.0.0.1). Затем он запросит ваше имя пользователя и пароль.

Это дает вам новую оболочку входа в систему (т. Е. Совершенно новую оболочку, которая не наследует ничего от текущей среды).

Вы можете проверить значение $PATHтам и отредактировать свои rc-файлы, пока оно не станет правильным. Это также полезно, чтобы узнать, сможете ли вы снова войти в систему после внесения изменений в важный файл.

Аарон Дигулла
источник
Вместо того, чтобы вводить имя пользователя / пароль, просто введите /bin/bash -i. Намного меньше хлопот.
Эд Хил
0

Как вы добавили эти повторяющиеся пути в переменную PATH? Вы, должно быть, редактировали один из ваших .файлов. ( .tcshrcили .bashrcи т. д. в зависимости от вашей конкретной системы / оболочки). Способ исправить это - снова отредактировать файл и удалить повторяющиеся пути.

Если вы не редактировали какие-либо файлы, и вы должны изменить PATH в интерактивном режиме. В этом случае изменения не будут «закрепляться», т.е. если вы откроете другую оболочку или выйдете из системы и снова войдете в систему, изменения автоматически исчезнут.

Обратите внимание, что есть также некоторые общесистемные файлы конфигурации, но вряд ли вы их изменили, поэтому, скорее всего, вы будете изменять файлы в своем личном домашнем каталоге (если вы хотите сделать эти изменения постоянными, как только вы выберете набор путей)

Левон
источник
0

Для простого шаблона копирования и вставки я использую этот фрагмент Perl:

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

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

Александр Щебликин
источник