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

Я 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

person charles hendry    schedule 25.07.2012    source источник
comment
где ты это 6 раз определял? в каких файлах?   -  person hovanessyan    schedule 25.07.2012
comment
возможный дубликат Каков самый элегантный способ удалить путь из переменной $ PATH в Bash?   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 17.10.2014
comment
См. Проблема с дублированием записей в $ PATH?   -  person loxaxs    schedule 01.11.2018


Ответы (12)


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

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

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

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

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

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

PATH=`echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'`
person sufinawaz    schedule 20.09.2013
comment
Это было полезно для меня, так как в / etc / profile был добавлен каталог, который я хотел исключить, но у меня нет доступа на запись в / etc. Спасибо :) - person Samizdis; 23.04.2014
comment
Совет: вы можете использовать другой разделитель в выражении sed, чтобы избежать экранирования \ /: PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||') - person iNecas; 12.12.2014
comment
Этот трюк помогает, когда я хочу сразу получить новый PATH и не хочу выходить из текущего терминала. Однако, чтобы избежать путаницы, следует поэкспериментировать с командой генерации PATH (т.е. echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'), прежде чем назначать ее PATH. - person biocyberman; 01.05.2015
comment
Это не сработает, если удаляемый путь оказывается 1-м путем в $PATH. Используйте этот: PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//') - person Robin Hsu; 13.04.2017
comment
не работает $ PATH=echo $ PATH | sed -e 's /: \ / scratch \ / sjn \ / anaconda \ / bin \ / python \ / $ //' '' для удаления / scratch / sjn / anaconda / bin / python - person Mona Jalal; 09.03.2018
comment
Я использовал тот, который рекомендован iNecas, но без знака доллара: PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir||') - person user3804598; 01.10.2019
comment
Вы также можете просто указать PATH=${PATH/':/home/wrong/dir'/} в своем файле запуска ... Это удалит первое вхождение этого шаблона. Если по какой-то причине он у вас будет несколько раз, то это будет: PATH=${PATH//':/home/wrong/dir'/}. И цитаты имеют значение :-) - person Flandraco; 10.04.2020
comment
Я попробовал каждого из Stefan van den Akker, iNecas, biocyberman и user3804598. Поскольку я не закрывал и не открывал терминал после каждого испытания, я не видел никаких изменений после каждого из них. Итак, я не могу сказать, какая из версий наконец сработала. По моим ощущениям, это был user3804598, так как это была последняя попытка, но я не уверен. В любом случае, спасибо за все вклады! - person soirbleu; 07.05.2020

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', orksh`. Я сомневаюсь, что это будет работать в командной оболочке 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)))
" )
person Aaron Hall    schedule 07.11.2017
comment
+1. работает ли pathremove () во всех вариантах оболочки, например, csh, ksh, bash и т. д.? кстати, в моем / etc / profile на RHEL нет partremove (), а есть только pathmunge (). - person Tagar; 21.10.2018
comment
@Tagar Я не даю никаких гарантий относительно совместимости со всеми остальными оболочками. Я предлагаю протестировать его на любой оболочке, которую вы используете, и если она не работает для вашей оболочки, вы можете использовать Python, если он у вас установлен - я добавил немного Python к ответу, чтобы описать, как. - person Aaron Hall; 21.10.2018
comment
Если я правильно прочитал 3.5.3 Расширение параметров оболочки, ${!PATHVARIABLE} - это своего рода косвенное обращение к переменной, но я не уверен, как это работает здесь. Не могли бы вы объяснить это, пожалуйста? - person loxaxs; 01.11.2018
comment
@loxaxs Это локальная переменная в этих функциях bash, объявленная с помощью встроенной функции local (которая может использоваться только внутри функции). Если у вас есть дополнительные вопросы, вам, вероятно, следует задать новый вопрос на сайте (после поиска сначала убедитесь, что вы не создаете точную копию ...). - person Aaron Hall; 01.11.2018
comment
Это действительно интересный ответ, спасибо за отзыв! Однако исходный вопрос об очистке испорченной переменной PATH, похоже, не решен изящно (хотя, я признаю, тогда при использовании этих функций нельзя было бы получить испорченный PATH с самого начала). - person Christian Herenz; 10.12.2019

Вот однострочный код, очищающий 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)}}')";
    
person GreenFox    schedule 13.08.2012
comment
кто нибудь тестировал? безопасно? - person Joe RR; 03.04.2018
comment
если у вас не установлен awk, он очищает ваш путь, я советую скопировать ваш путь в txt файл перед с помощью echo $ PATH - person Gabriel Pita; 18.04.2018
comment
У меня не работает ... У меня awk установлена, но некоторые дубликаты не удаляются. - person Christian Herenz; 10.12.2019

  1. Только 1_
  2. копировать детали в текстовый редактор
  3. удалить ненужные записи
  4. PATH= # pass new list of entries
person kawerewagaba    schedule 05.03.2019

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

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

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

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

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

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

person sabgenton    schedule 10.06.2015
comment
% означает совпадение, если в конце строки # находится в начале. - person sabgenton; 10.06.2015

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

person Kevin Nathan    schedule 07.07.2018
comment
+1 за решение. Кстати, он удалит дублирующиеся пути только в том случае, если они идут в списке один за другим. Вы можете изменить |uniq на |sort|uniq, чтобы исправить это, но это изменит порядок всех каталогов на пути, что я не считаю желаемым побочным эффектом. - person Tagar; 21.10.2018

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

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

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

person Levon    schedule 25.07.2012

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

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

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

person Leo    schedule 25.07.2012

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

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

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

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

person Aaron Digulla    schedule 25.07.2012
comment
Вместо того, чтобы вводить имя пользователя / пароль, просто введите /bin/bash -i. Намного меньше хлопот. - person Ed Heal; 25.07.2012

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

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

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

person Alexander Shcheblikin    schedule 15.02.2017

ПУТЬ = echo $PATH | sed 's/:/\n/g' | sort -u | sed ':a;N;$!ba;s/\n/:/g'

person guest    schedule 29.09.2020