PATH 변수에서 중복 항목 제거


9

.bashrc를 자주 수정 한 다음 소스를 만듭니다. 그러나 export PATH="~/bin:~/perl5/bin:$PATH"내 파일 과 같은 것이 있으면 파일을 PATH소스 할 때마다 환경 변수가 커집니다.

예를 들어, .bashrc가 처음 제공 될 때 PATH변수는로 구성됩니다 ~/bin:~/perl5/bin:/usr/bin:/bin.

두 번째로 구성됩니다 ~/bin:~/perl5/bin:~/bin:~/perl5/bin:/usr/bin:/bin.

세 번째로 구성됩니다 ~/bin:~/perl5/bin:~/bin:~/perl5/bin:~/bin:~/perl5/bin:/usr/bin:/bin.

PATH에없는 것을 추가하는 간단한 방법이 있습니까?

답변:


12

대부분의 배포판에서 사용 가능한 pathmunge () 함수를 사용하십시오 /etc/profile.

pathmunge () {
if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
   if [ "$2" = "after" ] ; then
      PATH=$PATH:$1
   else
      PATH=$1:$PATH
   fi
fi
}

편집 : zsh사용자의 경우 typeset -U <variable_name>경로 항목을 중복 제거합니다.


감사! /etc/profile데비안 레니에는 포함되어 있지 않으므로 내에 포함 .bashrc시킵니다.
Christopher Bottoms

사용법 : pathmunge /some/path배치됩니다 /some/path의 시작 부분 $PATHpathmunge /some/path after배치됩니다 /some/path의 끝에서$PATH
크리스토퍼 바지

현대 bash 쉘에서 hew 디렉토리가 현재 경로에 있는지 확인하는 더 깨끗한 방법 : if ! [[ $PATH =~ (^|:)$1($|:) ]] ; then.
Christopher Cashell

나는 이것을 사용하지 않을 것입니다. 순진한 버전이 PATH = / foo : $ PATH라고 말하면 / foo가 이기기를 원합니다. pathmunge /foo before그것을 달성하지 못합니다. 더 좋은 방법은 처음에 / foo를 추가 한 다음 나중에 중복을 제거하는 것입니다.
Don Hatch

3

이 문제가 발생하여 StackOverflow 질문에 나열된 기술 조합을 사용했습니다 . 다음은 기본 스크립트를 수정하고 싶지 않기 때문에 이미 설정된 실제 PATH 변수를 제거하는 데 사용한 것입니다.

    tmppath=(${PATH// /@})
    array=(${tmppath//:/ })
    for i in "${array[@]//@/ }"
    do
        if ! [[ $PATH_NEW =~ "$i" ]]; then
            PATH_NEW="${PATH_NEW}$i:";
        fi
    done;
    PATH="${PATH_NEW%:}"
    export PATH
    unset PATH_NEW

항상 이것을 조금 더 최적화 할 수는 있지만 변수를 올바르게 설정했는지 확인하기 위해 발생한 일을 표시하기 위해 원본에 추가 코드가 있습니다. 주목해야 할 또 다른 것은 다음을 수행한다는 것입니다.

  1. 스페이스 문자를 @ 문자로 바꾸십시오
  2. 배열을 나누다
  3. 배열을 반복
  4. 요소 문자열의 @ 문자를 공백으로 바꾸십시오

이것은 공백이있는 디렉토리를 처리 할 수 ​​있도록합니다 (Active Directory 사용자 이름이있는 삼바 홈 디렉토리에는 공백이있을 수 있습니다!)


경고 :이 구현에는 중대한 버그가 있습니다 !! 두 항목이 동일하지 않더라도 정규 표현식이 일치하기 때문에 /bin다른 항목이 있으면 제거 됩니다 /usr/bin!
Sukima

다음은 그 버그를 수정 한 대체 구현입니다 : github.com/sukima/dotfiles/blob/…
Sukima

1

경로를 명시 적으로 설정하십시오.


감사. 경로를 명시 적으로 설정하려고했지만 여러 환경에서 사용하는 .bashrc 파일이 있으므로 정확한 기본값 PATH이 항상 같지는 않습니다.
Christopher Bottoms

1

하나의 문자열 만 :

for i in $(echo $PATH|tr ":" "\n"|sort|uniq);do PATH_NEW="${PATH_NEW}$i:";done;PATH="${PATH_NEW%:}"

감사. 이 문제가 발생하기 어려운 이유는의 내용을 알파벳순 (또는 ASCII)으로 재정렬한다는 것입니다 $PATH. 나는 $PATH( /home/username기본값 같은 ) 시작 부분에 특정 디렉토리를 두어 내장 된 기본값 대신 내 개인 실행 파일 사본이 실행되도록합니다.
Christopher Bottoms

1

나는 당신이 이것을 해결할 수있는 두 가지 다른 방법을 생각할 수 있습니다. 첫 번째는 기본 PATH를 명시 적으로 설정하는 줄로 .bashrc를 시작하는 것입니다. 그러면 소스를 찾을 때마다 추가 디렉토리를 추가하기 전에 기본 PATH로 재설정됩니다.

예를 들어 다음을 추가하십시오.

# Reset the PATH to prevent duplication and to make sure that we include
# everything we want.
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

또는 경로에 항목을 추가하기 전에 항목을 확인할 수 있습니다. 그렇게하려면 다음과 같은 것을 사용해야합니다.

if ! [[ $PATH =~ '~/perl5/bin' ]]
then
    PATH="~/perl5/bin:$PATH"
fi

그러나 많은 항목을 추가하면 후자가 약간 반복되는 경향이 있으므로 전자를 사용하는 경향이 있습니다. 이것을 사용하고 많은 항목을 추가 할 계획이라면 bash 함수를 작성하여 처리하는 것이 현명합니다.

참고 : 두 번째 옵션은 최신 버전 bash로 작성된 대로만 작동 할 수 있습니다. 정규식 지원은 Bourne Shell (/ bin / sh) 기능이 아니며 다른 쉘에는 없을 수 있습니다. 또한 따옴표 사용이 필요하지 않거나 최신 버전의 bash에서 문제를 일으킬 수도 있습니다.


감사. 경로를 명시 적으로 설정하려고했지만 여러 환경에서 사용하는 .bashrc 파일이 있으므로 정확한 기본값 PATH이 항상 같지는 않습니다.
Christopher Bottoms

스크립트를 체크인하여 로컬 호스트 이름이 무엇인지 확인한 다음 해당 서버에 대한 절대 경로를 적절하게 설정하여 처리 할 수 ​​있습니다.
Christopher Cashell

오타 :! 에서 누락되었습니다 if. 또한, 당신이 바로 말할 수 있도록 공백으로 구분 된 인수를 통해 루프 기능이 점을 쉽게 만들 수 (나에게) 의외로입니다 : add_to_PATH ~/perl5/bin ~/.bin unix.stackexchange.com/a/4973/28760 (필자는 추측 case문을 사용하는 휴대 성이 ,하지만 당신 if은 나에게 더 명확합니다). 이 질문에 perl5가 추가되는 이상한 우연의 일치를 편집하십시오 !
13ren

@ 13ren : 메모 주셔서 감사합니다. 또한 PATH 세트 줄에 큰 따옴표 대신 작은 따옴표를 사용했음을 깨달았습니다. 작성된대로 기존 경로를 변수 이름으로 대체했을 것입니다. 죄송합니다! 분명히 그것은 오타로 나에게 나쁜 입장이었습니다. 둘 다 지금 수정되었습니다.
Christopher Cashell

0

내 해결책은 다음과 같습니다. PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

후행을 남기지 않는 좋은 쉬운 하나의 라이너 :

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.