Удалите лишние пути из переменной $ 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


Ответы:


122

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

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

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

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


да, я установил их постоянно в 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\/$//'`

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)}}')";
    

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

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

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::`

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.