PATH에 경로를 올바르게 추가하는 방법은 무엇입니까?


922

PATH환경 변수에 새 경로를 추가 해야하는 곳이 궁금 합니다. 편집 .bashrc(예 :)을 통해이 작업을 수행 할 수 있다는 것을 알고 있지만이 작업을 수행하는 방법은 명확하지 않습니다.

이 방법:

export PATH=~/opt/bin:$PATH

아니면 이거?

export PATH=$PATH:~/opt/bin

printf '\ nPATH = $ PATH : "경로 추가"\ n 내보내기 경로 \ n'>> ~ / .bashrc
Sudoer


예를 들어 PATH=$PATH:$HOME/.local/bin:$HOME/bin, 추가 된 경로가 이미 있으면 다음 과 같이 분리하여 다른 경로를 추가 할 수 있습니다 PATH=$PATH:$HOME/.local/bin:$HOME/bin:/home/ec2-user/pear/bin.
Sandeepan Nath

2
이 답변은 모든 Linux 버전에서 작동합니까?
Ungeheuer

답변:


1033

간단한 것들

PATH=$PATH:~/opt/bin

또는

PATH=~/opt/bin:$PATH

~/opt/bin마지막 에 추가 할 것인지 (여러 디렉토리에 동일한 이름의 프로그램이있는 경우 다른 모든 디렉토리에서 검색 할 것인지 ) 또는 시작 (다른 모든 디렉토리보다 먼저 검색 할 것인지)에 추가할지 여부에 따라 다릅니다 .

여러 항목을 동시에 추가 할 수 있습니다. PATH=$PATH:~/opt/bin:~/opt/node/bin또는 주문의 변형이 잘 작동합니다. export추가 합병증이 있으므로 행의 시작 부분에 두지 마십시오 (아래 "bash 이외의 쉘에 대한 참고 사항"참조).

당신이 경우 PATH여러 가지 구성 요소에 의해 구축됩니다, 당신은 중복 항목으로 끝날 수 있습니다. 참조 홈 디렉토리 경로가 명령을 유닉스에 의해 발견에 추가하는 방법? awk 명령으로 중복 $의 PATH 항목을 제거 중복을 추가 피하거나 제거 할 수 있습니다.

그런데 일부 배포판 ~/bin은 PATH가 있으면 자동으로 PATH에 넣습니다 .

넣을 곳

수정 라인을 넣어 PATH에서 ~/.profile, 또는 ~/.bash_profile그 당신이 무엇을합니다.

참고 ~/.bash_rc모든 프로그램에서 읽을되지 않고 ~/.bashrc배쉬의 대화 형 인스턴스의 구성 파일입니다. 에 환경 변수를 정의해서는 안됩니다 ~/.bashrc. 오른쪽 장소는 다음과 같은 환경 변수를 정의 할 수 PATH있다 ~/.profile(또는 ~/.bash_profile당신의 bash 이외의 쉘을 걱정하지 않는 경우). 그들과 어떤 것을 사용해야합니까?를 참조하십시오 .

/etc/environment또는에 넣지 마십시오 ~/.pam_environment: 이들은 셸 파일이 아니며 $PATH거기에서 와 같이 대체를 사용할 수 없습니다 . 이러한 파일에서는 변수를 재정의 할 수 있으며 추가 할 수는 없습니다.

일부 시스템 스크립트의 잠재적 합병증

export변수가 이미 환경에있는 경우 필요하지 않습니다 . 변수 값의 변경 사항이 환경에 반영됩니다 .¹ PATH는 거의 항상 환경에 있습니다. 모든 유닉스 시스템은 초기에 (보통 첫 번째 프로세스에서) 매우 일찍 설정했습니다.

로그인시 PATH이미 환경에 있고 일부 시스템 디렉토리를 포함하고있을 수 있습니다. 어떤 종류의 가상 환경을 설정하는 동안 조기에 실행될 수있는 스크립트를 작성하는 경우 PATH비어 있지 않고 내 보내야합니다. PATH여전히 설정되어 있지 않으면 다음과 같이 PATH=$PATH:/some/directory설정 PATH되고 :/some/directory빈 구성 요소 시작 부분은 현재 디렉토리 (와 같은 .:/some/directory)를 의미합니다 .

if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi

bash 이외의 쉘에 대한 참고 사항

bash는, KSH 및 zsh을에서 export특수 구문이며, 모두 PATH=~/opt/bin:$PATH하고 export PATH=~/opt/bin:$PATH도 옳은 일을. 대시 ( /bin/sh많은 시스템에 있음) 와 같은 다른 Bourne / POSIX 스타일 쉘 export에서는 일반적인 명령으로 구문 분석되며 두 가지 차이점이 있습니다.

대시 같은 껍질에 그래서, export PATH=~/opt/bin:$PATH설정 PATH리터럴 문자열 ~/opt/bin/:값으로 다음에 PATH최초의 우주까지. PATH=~/opt/bin:$PATH(맨손으로 할당) 따옴표필요하지 않으며 옳은 일을합니다. 당신이 사용하려는 경우 export휴대용 스크립트에서, 당신은 쓸 필요 export PATH="$HOME/opt/bin:$PATH"하거나 PATH=~/opt/bin:$PATH; export PATH(또는 PATH=$HOME/opt/bin:$PATH; export PATH이동성이 수락하지 않았습니다 Bourne 쉘 균일하게하기 위해 export var=value및 틸드 확장을하지 않았다)를.

¹ 이것은 Bourne 쉘 (현대 POSIX 스타일 쉘이 아닌 실제 Bourne 쉘에서와 같음)에는 해당되지 않았지만 요즘에는 그러한 오래된 쉘이 발생할 가능성이 거의 없습니다.


여전히 수출로 인한 합병증을 이해할 수 없습니다. 당신은 그것을 단순화 할 수 있습니까?
priojeet priyom

@priojeetpriyom 간단한 설명 : 필요하지 않습니다 export.
Gilles

이 답변에 대해 자세히 설명해 주셔서 감사합니다. " ~ / .bashrc에 환경 변수를 정의하면 안됩니다. "라고 말하지만 불행히도 경로를 수정하는 시스템에 설치 한 프로그램 (FZF 및 Rust 's Cargo)의 100 %는에서 경로를 수정합니다 .bashrc. FZF가 Rust로 작성 되었기 때문에 Rust 패턴을 따르고 있다고 가정합니다.
icc97

83

어느 쪽이든 효과가 있지만 동일한 작업을 수행하지 않습니다. 요소 PATH가 왼쪽에서 오른쪽으로 확인됩니다. 첫 번째 예에서 in의 실행 파일은 예를 들어 in에 ~/opt/bin설치된 것보다 우선 /usr/bin합니다.

특히 안전 관점에서 전면에 경로를 추가하는 것은 위험합니다. 누군가가 귀하의에 대한 쓰기 권한을 얻을 수있는 경우 ~/opt/bin, 예를 들어 ls거기에 다른 것을 넣을 수 있기 때문에 대신 사용할 수 있기 때문입니다. 의 /bin/ls몰래. 이제는 ssh브라우저 또는 선택에 대해 동일하게 생각하십시오 ... (경로에.


6
그러나 사용자 정의 된 사용자 정의 버전을 원하면 ls디렉토리 앞에 디렉토리를 넣어야합니다 /bin.
Barmar

16
또는 alias ls = myls
waltinator 1

36

질문 2로 인해 혼란 스럽습니다 (관련이없는 문제로 인해 질문에서 제거되었으므로).

다른 줄에 더 많은 경로를 추가 할 수있는 방법은 무엇입니까? 처음에는 이것이 트릭을 수행 할 수 있다고 생각했습니다.

export PATH=$PATH:~/opt/bin
export PATH=$PATH:~/opt/node/bin

그러나 두 번째 과제는을 추가 할 ~/opt/node/bin뿐만 아니라 PATH이전에 할당 된 전체 이기 때문에 아닙니다 .

가능한 해결 방법은 다음과 같습니다.

export PATH=$PATH:~/opt/bin:~/opt/node/bin

그러나 가독성을 위해 하나의 경로에 대해 하나의 할당을 선호합니다.

당신이 말하는 경우

PATH=~/opt/bin

그건 모두 당신의 PATH에있을 것이다. PATH는 환경 변수 일 뿐이므로 PATH에 추가하려면 원하는 내용으로 변수를 다시 작성해야합니다. 즉, 질문 2의 예로 제시하는 것은 질문의 요점을 완전히 누락하지 않는 한 정확하게하려는 것입니다.

코드에서 두 양식을 모두 사용합니다. 잠재적으로 누락되는 디렉토리를 수용하기 위해 작업하는 모든 시스템에 다음과 같은 일반 프로파일을 설치했습니다.

export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11
# add optional items to the path
for bindir in $HOME/local/bin $HOME/bin; do
    if [ -d $bindir ]; then
        PATH=$PATH:${bindir}
    fi
done

2
당신은 질문 2의 예에 대해 맞습니다, 그것은 효과가 있습니다. 내 시스템의 또 다른 PATH 관련 문제로 인해 혼란 스러웠습니다. 그 죄송합니다.
Paolo

26

방탄 / 접기 방법

추가와 추가를 선택할 때 고려해야 할 사항이 많이 있습니다. 그들 중 많은 사람들이 다른 답변으로 다뤄 졌으므로 여기서는 반복하지 않겠습니다.

중요한 점은 시스템 스크립트가 이것을 사용하지 않더라도 (왜 그런지 궁금합니다) * 1 이지만 $HOME/binPATH 환경 변수에 경로 (예 :)를 추가하는 방탄 방법 은 다음과 같습니다.

PATH="${PATH:+${PATH}:}$HOME/bin"

추가 (대신에 PATH="$PATH:$HOME/bin") 및

PATH="$HOME/bin${PATH:+:${PATH}}"

붙이는 (대신에 PATH="$HOME/bin:$PATH")

이것은 가짜 선두가 / 콜론을 후행하는 경우 피할 수 $PATH바람직하지 않은 부작용이있을 수 있으며, 이는 초기에 비어 악몽이 될 수있다 (찾기 어려운, 이 대답은 간단 경우로 취급 awk웨이를).

설명 ( 쉘 매개 변수 확장에서 ) :

${parameter:+word}

경우 parameternull 또는 설정 해제 아무것도 달리 팽창, 치환되지 word치환된다.

따라서 ${PATH:+${PATH}:}1) PATHnull이거나 설정되지 않은 경우 2) ${PATH}:, 설정되어 있으면 아무것도 확장되지 않습니다 PATH.

참고 : 이것은 bash 용입니다.


* 1 방금 이와 같은 스크립트가 devtoolset-6/enable실제로 이것을 사용 한다는 것을 알았습니다 .

$ cat /opt/rh/devtoolset-6/enable
# General environment variables
export PATH=/opt/rh/devtoolset-6/root/usr/bin${PATH:+:${PATH}}
...

24

Linux는 $PATH환경 변수를 사용하여 실행 가능한 검색 경로를 결정합니다 . / data / myscripts 디렉토리를 $PATH환경 변수 의 시작 부분에 추가하려면 다음을 사용하십시오.

PATH=/data/myscripts:$PATH

해당 디렉토리를 경로 끝에 추가하려면 다음 명령을 사용하십시오.

PATH=$PATH:/data/myscripts

그러나 스크립트 내에서 환경 변수를 설정하면 해당 변경 사항이 스크립트 내에서만 적용되므로 위의 내용만으로는 충분하지 않습니다. 이 제한에는 두 가지 방법 만 있습니다.

  • 스크립트 내에서 환경 변수를 내 보내면 스크립트에서 호출 한 모든 프로그램 내에서 유효합니다. 스크립트를 호출 한 프로그램에서는 효과가 없습니다.
  • 스크립트를 호출하는 프로그램이 호출하는 대신 포함하여 포함하는 경우 스크립트의 모든 환경 변경은 호출 프로그램 내에서 유효합니다. 이러한 포함은 dot 명령 또는 source 명령으로 수행 할 수 있습니다.

예 :

$HOME/myscript.sh
source $HOME/myscript.sh

포함은 기본적으로 "호출"스크립트에 "호출"스크립트를 통합합니다. C의 #include와 같습니다. 따라서 "호출"스크립트 나 프로그램에서 효과적입니다. 그러나 물론 호출 프로그램이 호출하는 프로그램이나 스크립트에는 효과적이지 않습니다. 콜 체인 전체에 적용하려면 내보내기 명령으로 환경 변수 설정을 따라야합니다.

예를 들어, bash 쉘 프로그램은 .bash_profile 파일의 내용을 포함하여 통합합니다. .bash_profile에 다음 두 줄을 배치하십시오.

PATH=$PATH:/data/myscripts
export PATH

이 두 줄의 코드를 효과적으로 bash 프로그램에 넣습니다. 따라서 bash 내에서 $ PATH 변수는을 포함하며 $HOME/myscript.sh, export 문으로 인해 bash가 호출 한 모든 프로그램에는 변경된 $PATH변수가 있습니다. 그리고 bash 프롬프트에서 실행하는 모든 프로그램은 bash에 의해 호출되므로 bash 프롬프트에서 실행하는 모든 작업에 새 경로가 적용됩니다.

결론은 경로에 새 디렉토리를 추가하려면 쉘에 포함 된 스크립트 내에서 $ PATH 환경 변수에 디렉토리를 추가하거나 추가해야하며 환경 변수를 내 보내야한다는 것 $PATH입니다.

더 자세한 정보는 여기


19

한동안 나는 나와 함께 두 가지 기능을 유지 한 pathadd하고 pathrm그 중복에 대해 걱정할 필요없이 경로에 요소를 추가로 지원합니다.

pathadd단일 경로 인수와 선택적인 after인수를 사용 PATH합니다.

거의 모든 상황에서 경로에 추가하는 경우 경로에 이미있는 것을 무시하고 싶을 가능성이 있으므로 기본적으로 앞에 추가하도록 선택합니다.

pathadd() {
    newelement=${1%/}
    if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then
        if [ "$2" = "after" ] ; then
            PATH="$PATH:$newelement"
        else
            PATH="$newelement:$PATH"
        fi
    fi
}

pathrm() {
    PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}

이것을 PATH 환경을 변경하려는 스크립트에 넣고 지금 할 수 있습니다.

pathadd "/foo/bar"
pathadd "/baz/bat" after
export PATH

경로가 이미 있으면 경로에 추가하지 않아야합니다. 지금 /baz/bat시작하려면 시작하십시오.

pathrm "/baz/bat"
pathadd "/baz/bat"
export PATH

경로가 이미 배가되지 않은 경우 경로를 앞으로 이동할 수 있습니다.


PATH에 디렉토리가 있는지 확인하는 관련적이고 깔끔한 접근 방식 : unix.stackexchange.com/a/32054/135943
Wildcard

9

다른 배포판에 대해서는 말할 수 없지만 Ubuntu에는 / etc / environment 파일이 있으며 이는 모든 사용자의 기본 검색 경로입니다. 내 컴퓨터는 본인 만 사용하므로 스크립트에 임시로 추가하지 않는 한 원하는 경로를 원하는 경로에 저장합니다.


6

다음과 PATH=/a/b:$PATH같이 경로를 추가하는 "잘못된"방법으로 사용되는 상황 이 있습니다 PATH.

  1. 실제로 디렉토리가 아닌 경로 추가
  2. 이미 PATH같은 형식으로 된 경로 추가
  3. 상대 경로 추가 (검색된 실제 디렉토리는 현재 작업 디렉토리를 변경함에 따라 변경되므로)
  4. 이미 PATH다른 형식 으로 되어 있는 경로를 추가합니다 (예 : 심볼릭 링크 또는로 인한 별칭 ..).
  5. 4를 수행하지 않으면 PATH의 다른 항목을 재정의하려는 경우 경로를 앞으로 이동하지 마십시오 PATH.

이 (Bash-only) 기능은 위 상황에서 "올바른 일"을 수행하고 (예외는 아래 참조) 오류 코드를 반환하며 사람에게 좋은 메시지를 인쇄합니다. 오류 코드와 메시지는 원하지 않을 때 비활성화 할 수 있습니다.

prepath() {
    local usage="\
Usage: prepath [-f] [-n] [-q] DIR
  -f Force dir to front of path even if already in path
  -n Nonexistent dirs do not return error status
  -q Quiet mode"

    local tofront=false errcode=1 qecho=echo
    while true; do case "$1" in
        -f)     tofront=true;       shift;;
        -n)     errcode=0;          shift;;
        -q)     qecho=':';          shift;;
        *)      break;;
    esac; done
    # Bad params always produce message and error code
    [[ -z $1 ]] && { echo 1>&2 "$usage"; return 1; }

    [[ -d $1 ]] || { $qecho 1>&2 "$1 is not a directory."; return $errcode; }
    dir="$(command cd "$1"; pwd -P)"
    if [[ :$PATH: =~ :$dir: ]]; then
        $tofront || { $qecho 1>&2 "$dir already in path."; return 0; }
        PATH="${PATH#$dir:}"        # remove if at start
        PATH="${PATH%:$dir}"        # remove if at end
        PATH="${PATH//:$dir:/:}"    # remove if in middle
    fi
    PATH="$dir:$PATH"
}

단,이 함수는 PATH다른 방법 을 통해 추가 된 경로를 정규화 할 수 없으므로 경로의 비정규 별칭이에 PATH있는 경우 복제본이 추가됩니다. PATH상대 경로는 전달 될 때 명백한 의미를 prepath갖지만 이미 경로에있을 때 현재 작업 디렉토리가 추가되었을 때의 현재 상태를 알 수 없기 때문에 이미 존재하는 경로를 정규화하려고 시도하는 것은 까다로운 제안 입니다.


상대 경로와 관련하여 : '-r'스위치를 사용하면 경로를 절대 경로로 만들지 않고 경로를 추가하고 경로를 추가하기 전에 절대 경로로 찾을 수 있습니까? 이것이 스크립트라면 다른 쉘에서 사용할 수 있습니다. 함수로 사용하면 어떤 이점이 있습니까? 좋은 코드!
hoijui

1
@hoijui 현재 환경을 수정하고 있기 때문에 함수 여야합니다. 스크립트 인 경우 스크립트를 실행하는 하위 프로세스의 환경을 수정하며 스크립트가 종료되면 $PATH이전 과 동일 합니다. 에 관해서는 -r아니오, 나는 일반적인 도구에서 상대 경로 $PATH가 너무 신뢰할 수없고 이상 하다고 생각합니다 (경로가 변경 될 때마다 경로가 변경됩니다 cd!).
Curt J. Sampson

5

나에게 (Mac OS X 10.9.5의 경우) /mypathname파일에 경로 이름 (예 :)을 추가하면 /etc/paths매우 효과적이었습니다.

편집하기 전에 다음을 echo $PATH반환합니다.

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

/etc/paths쉘을 편집 하고 다시 시작한 후에 $ PATH 변수가 추가됩니다 /pathname. 실제로 다음을 echo $PATH반환합니다.

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname

그 일이 변수 /mypathname에 추가되었습니다 $PATH.


3
/ etc / paths 파일 자체를 편집하는 것보다 /etc/paths.d 디렉토리에 파일을 추가하는 것이 좋습니다.
rbrewer

4

PATH환경 변수에 새 경로를 추가하려면 다음을 수행하십시오 .

export PATH=$PATH:/new-path/

이 변경 사항을 여는 모든 쉘에 적용하려면, 쉘 이 호출 될 때 소스가 제공 할 파일에 추가하십시오 . 다른 쉘에서는 다음과 같습니다.

  • Bash Shell : ~ / .bash_profile, ~ / .bashrc 또는 프로파일
  • Korn Shell : ~ / .kshrc 또는 .profile
  • Z 쉘 : ~ / .zshrc 또는 .zprofile

예 :

# export PATH=$PATH:/root/learning/bin/
# source ~/.bashrc
# echo $PATH

위 출력에서 ​​제공된 경로를 볼 수 있습니다.


4

내 해결책은 다음과 같습니다.

PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

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


1
-bash : awk : 해당 파일 또는 디렉토리 없음 -bash : sed : 해당 파일 또는 디렉토리 없음
davidcondrey

1
@davidcondrey-awk와 sed는 매우 일반적인 외부 명령입니다. 이 답변 은 순수한 bash 방법을 제공하므로 awk 및 / 또는 sed가 없거나 (또는 ​​해당 디렉토리가 경로에 있지 않은 경우에도) 작동합니다.
sancho.s
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.