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의 시작 부분 $PATH과 pathmunge /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.