긴 $ PATH를보다 편하게 편집 할 수 있습니까?


35

~ / .bashrc에 $ PATH에 몇 개의 디렉토리를 추가하고 싶습니다.

내 $ PATH는 꽤 길기 때문에 포함 된 디렉토리와 순서를 확인하기가 약간 어렵습니다.

~ / .bashrc를 다음과 같이 수정할 수 있다는 것을 알고 있습니다.

PATH=$PATH:/some/dir
PATH=$PATH:/another/dir:/yet/another
PATH=$PATH:/and/another
...

쉽게 읽을 수 있습니다. 그러나 지난 몇 년 동안 Bash가 긴 PATH를 더 쉽게 지정할 수있는 구문을 얻었는지 궁금합니다. 예를 들어 다음과 유사한 구문에 대해 환상적입니다.

PATH=:((
  /some/dir
  /another/dir
  /yet/another
  /and/another
  ...
))

그런 구문이 유효하지 않다는 것을 알고 있습니다. 쉬운 것이 있는지 궁금합니다. 있습니까?


기존의 튜토리얼을 통해 경로 설정 PATH=foo:$PATH이 성장마다 시간을 유지하기 때문에 잘못된 것을 source ~/.bashrc, 심지어 exec bash도움이 (가)부터 할 수 없습니다 $PATH입니다 export.
林果 皞

답변:


25

변수에 경로를 추가하거나 추가하기 위해 편의 기능 세트를 사용합니다. 함수는 "pathfuncs"라는 contrib 파일의 Bash 배포 tarball에 들어 있습니다.

  • add_path는 PATH 변수의 끝에 항목을 추가합니다
  • pre_path는 PATH 변수의 시작 부분에 항목을 추가합니다
  • del_path는 어디에 있든지 PATH 변수에서 항목을 제거합니다.

변수를 두 번째 인수로 지정하면 PATH 대신 변수를 사용합니다.

편의상 다음과 같습니다.

# is $1 missing from $2 (or PATH) ?
no_path() {
    eval "case :\$${2-PATH}: in *:$1:*) return 1;; *) return 0;; esac"
}
# if $1 exists and is not in path, append it
add_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1"
}
# if $1 exists and is not in path, prepend it
pre_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}"
}
# if $1 is in path, remove it
del_path () {
  no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: |
    sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"`
}

이를 bash 시작 파일에 추가하면 다음과 같이 PATH에 추가 할 수 있습니다.

pre_path $HOME/bin
add_path /sbin
add_path /usr/sbin

또는 다른 변수를 지정하십시오.

pre_path $HOME/man MANPATH
pre_path $HOME/share/man MANPATH
add_path /usr/local/man MANPATH
add_path /usr/share/man MANPATH

pre_paths를 먼저두고 add_paths를 두 번째로하는 rc 파일에서이 방법을 사용합니다. 모든 경로 변경 사항을 한눈에 쉽게 이해할 수 있습니다. 또 다른 이점은 줄이 짧아 필요한 경우 줄에 후행 주석을 추가 할 수 있다는 것입니다.

이것들은 함수이기 때문에 add_path $(pwd)현재 디렉토리를 경로에 추가하는 것과 같이 명령 행에서 대화식으로 사용할 수 있습니다 .


감사. 귀하의 코드를 확인했으며 작동합니다. 놀랍게도, 나는 또한 del_path를 사용하는 것을 발견했습니다 ( "."는 어떤 상황에서는 내 경로에 들어갑니다. 악마는 어디에서 왔는지 알기 때문에 del_path .)
Niccolo M.

안녕. bashrc 스크립트 에서이 pathfuncs를 소스 (포함) 할 수 있습니까? 아니면 복사 / 붙여 넣기해야합니까?
Cristiano

@Cristiano Either가 작동합니다. 정말 당신에게 달려 있습니다.
불가사리

11

좋아, 나는 다음과 같은 해결책을 알아 냈다. (쉘 구문이 진행되는 한) 우아하다고 생각한다. Bash의 배열 구문과 요소를 결합 하는 깔끔한 방법 을 사용합니다.

paths=(
  /some/dir
  /another/dir
  '/another/dir with spaces in it'
  /yet/another
  /and/another
  /end
)
paths_joined=$( IFS=: ; echo "${paths[*]}" )

PATH=$paths_joined:$PATH

경보!

@terdon 및 @Starfish의 솔루션과 달리이 솔루션 에는 문제가 있음이 밝혀졌습니다 . 먼저 경로가 PATH에 있는지 확인하지 않습니다. 따라서이 코드를 ~ / .bashrc (~ / .profile이 아닌)에 넣고 싶기 때문에 중복 경로가 PATH에 들어갑니다. 따라서이 솔루션을 사용하지 마십시오 (~ / .profile에 넣지 않는 한 (또는 Bash 특정 구문이 있으므로 ~ / .bash_profile이 더 좋습니다)).


1
아주 좋아요 이미 답변을 찾았을 때 다른 사람이 해결책을 제시하지 않도록 답변을 수락 할 수 있습니까? 감사합니다
기본

중복 경로는 실제로 문제가되지 않습니다. PATH실제로 성능 문제를 일으킬 수있는 충분한 디렉토리를 추가 할 가능성은 거의 없습니다 (특히 셸이 성공적인 조회를 캐시하기 때문에).
chepner

5

내에서 아래 기능을 사용합니다 ~/.bashrc. 이전 실험실의 시스템 관리자로부터 얻은 것이지만 그가 작성한 것은 아닙니다. 이 줄을 ~/.profile또는에 추가하십시오 ~/.bashrc.

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

여기에는 여러 가지 장점이 있습니다.

  • 에 새 디렉토리를 추가하는 $PATH것은 간단합니다. pathmunge /foo/bar;
  • 중복 된 항목을 피합니다.
  • 의 시작 ( pathmunge /foo/bar또는 끝 ( pathmunge /foo/bar이후)에 새 항목을 추가할지 여부를 선택할 수 있습니다 $PATH.

쉘의 초기화 파일에는 다음과 같은 내용이 포함됩니다.

pathmunge /some/dir
pathmunge /another/dir
pathmunge '/another/dir with spaces in it'
pathmunge /yet/another
pathmunge /and/another
pathmunge /end

감사. 그러나 @Starfish의 솔루션은 생성되지 않기 때문에 선택합니다 grep.
Niccolo M.

2
@NiccoloM. 문제 없습니다, 당신이 선호하는 것을 받아들입니다. 불가사리의 접근 방식에주의하십시오. 임의의 코드로 실행하면 임의의 코드가 실행 eval되므로 잘못된 인수로 실행하면 심각한 손상을 초래할 수 있습니다.
terdon

참고 빠른 기능은 외부 명령없이 그렇게하기 위해 레드햇에 있는지 grep, 볼 bugzilla.redhat.com/show_bug.cgi?id=544652#c7
林果皞

4

~ / .bashrc에 $ PATH에 몇 개의 디렉토리를 추가하고 싶습니다.

Cygwin에서 다음을 사용합니다. 다른 버전의 bash에서 작동해야합니다. unset PATH현재를 기반으로 빌드를 제거 할 수 있습니다 PATH(이를 수행하면 :구분 기호를 올바르게 추가하는 방법을 알아야 할 수도 있습니다 ).

노트 :

  • 한때 기능 에이 기능이 bash있었지만 디스크 충돌 후 손실되었습니다.

.bash_profile:

# Build up the path using the directories in ~/.path_elements
unset PATH
while read line; do 
  PATH="${PATH}$line"; 
done < ~/.path_elements

...

# Add current directory to path
export PATH=".:${PATH}"

에서 ~/.path_elements:

/home/DavidPostill/bin:
/usr/local/bin:
/usr/bin:
/c/Windows/system32:
/c/Windows

감사. 귀하의 답변은 비슷한 솔루션을 개발하도록 영감을주었습니다. (경로를 따로 파일로 저장하는 것은 귀찮습니다.)
Niccolo M.

1

나는 이것을 .bashrc (및 일반적으로 bash 대신 사용 가능한 곳에서 zsh를 사용하기 때문에 .zshrc)에서 사용합니다. 물론, 수동으로 디렉토리를 추가해야하지만, 디렉토리를 업데이트 할 때 새 서버로 디렉토리를 계속 복사 할 수 있으며 존재하지 않는 디렉토리로 새 서버의 PATH가 생성되는 것을 걱정하지 않아도됩니다.

##
## 경로
##
## PATH를 막는 대신
##이 서버에 적합하지 않습니다. 우리가 추가 한 것에 대해 지능적으로 노력하십시오.
##
PATH = / usr / local / sbin : / usr / local / bin : / usr / sbin : / usr / bin : / sbin : / bin
[-d / cs / sbin] && PATH = / cs / sbin : $ PATH
[-d / cs / bin] && PATH = / cs / bin : $ PATH
[-d / usr / ucb] && PATH = $ PATH : / usr / ucb
[-d / usr / ccs / bin] && PATH = $ PATH : / usr / ccs / bin
[-d / usr / local / ssl / bin] && PATH = $ PATH : / usr / local / ssl / bin
[-d / usr / krb5 / bin] && PATH = $ PATH : / usr / krb5 / bin
[-d / usr / krb5 / sbin] && PATH = $ PATH : / usr / krb5 / sbin
[-d / usr / kerberos / sbin] && PATH = $ PATH : / usr / kerberos / sbin
[-d / usr / kerberos / bin] && PATH = $ PATH : / usr / kerberos / bin
[-d /cs/local/jdk1.5.0/bin] && PATH = $ PATH : /cs/local/jdk1.5.0/bin
[-d /usr/java/jre1.5.0_02/bin] && PATH = $ PATH : /usr/java/jre1.5.0_02/man
[-d /usr/java1.2/bin] && PATH = $ PATH : /usr/java1.2/bin
[-d /cs/local/perl5.8.0/bin] && PATH = $ PATH : /cs/local/perl5.8.0/bin
[-d / usr / perl5 / bin] && PATH = $ PATH : / usr / perl5 / bin
[-d / usr / X11R6 / bin] && PATH = $ PATH : / usr / X11R6 / bin
[-d / etc / X11] && PATH = $ PATH : / etc / X11
[-d / opt / sfw / bin] && PATH = $ PATH : / opt / sfw / bin
[-d / usr / local / apache / bin] && PATH = $ PATH : / usr / local / apache / bin
[-d / usr / apache / bin] && PATH = $ PATH : / usr / apache / bin
[-d / cs / admin / bin] && PATH = $ PATH : / cs / admin / bin
[-d / usr / openwin / bin] && PATH = $ PATH : / usr / openwin / bin
[-d / usr / xpg4 / bin] && PATH = $ PATH : / usr / xpg4 / bin
[-d / usr / dt / bin] && PATH = $ PATH : / usr / dt / bin

나는 내 MANPATH에 대해 동일한 작업을 수행합니다.

##
## MANPATH
##
## MANPATH를 사용하여 디렉토리를 클로버 링하는 대신
##이 서버에 적합하지 않습니다. 우리가 추가 한 것에 대해 지능적으로 노력하십시오.
##
MANPATH = / usr / local / man
[-d / usr / share / man] && MANPATH = $ MANPATH : / usr / share / man
[-d / usr / local / share / man] && MANPATH = $ MANPATH : / usr / local / share / man
[-d / usr / man] && MANPATH = $ MANPATH : / usr / man
[-d / cs / man] && MANPATH = $ MANPATH : / cs / man
[-d / usr / krb5 / man] && MANPATH = $ MANPATH : / usr / krb5 / man
[-d / usr / kerberos / man] && MANPATH = $ MANPATH : / usr / kerberos / man
[-d / usr / local / ssl / man] && MANPATH = $ MANPATH : / usr / local / ssl / man
[-d /cs/local/jdk1.5.0/man] && MANPATH = $ MANPATH : /cs/local/jdk1.5.0/man
[-d /usr/java/jre1.5.0_02/man] && MANPATH = $ MANPATH : /usr/java/jre1.5.0_02/man
[-d /usr/java1.2/man] && MANPATH = $ MANPATH : /usr/java1.2/man
[-d / usr / X11R6 / man] && MANPATH = $ MANPATH : / usr / X11R6 / man
[-d / usr / local / apache / man] && MANPATH = $ MANPATH : / usr / local / apache / man
[-d / usr / local / mysql / man] && MANPATH = $ MANPATH : / usr / local / mysql / man
[-d /cs/local/perl5.8.0/man] && MANPATH = $ MANPATH : /cs/local/perl5.8.0/man
[-d / usr / perl5 / man] && MANPATH = $ MANPATH : / usr / perl5 / man
[-d / usr / local / perl / man] && MANPATH = $ MANPATH : / usr / local / perl / man
[-d /usr/local/perl5.8.0/man] && MANPATH = $ MANPATH : /usr/local/perl5.8.0/man
[-d / usr / openwin / man] && MANPATH = $ MANPATH : / usr / openwin / man

존재하지 않는 디렉토리를 PATH에 추가 할 염려없이 이기종 환경의 시스템에 복사 할 수있는 단일 파일을 갖는 것 외에도,이 방법은 디렉토리가 PATH에 표시되기를 원하는 순서를 지정할 수 있다는 이점이 있습니다. 각 정의의 첫 번째 줄은 PATH 변수를 완전히 재정의하기 때문에 중복 항목을 추가하지 않고 쉘을 업데이트하기 위해 .bashrc를 업데이트하고 편집 한 후 소스를 만들 수 있습니다 (오래 전에 " $ PATH = $ PATH : / new / dir "을 선택하면 원하는 순서대로 깨끗한 복사본을 얻을 수 있습니다.


1
대안 제안 : d="/usr/share/man" ; [ -d "$d" ] && MANPATH="$MANPATH:${d}"짧고 새 디렉토리를 추가하는 것이 더 쉬울 것입니다 (줄을 복사하고 첫 번째 "d = ...."부분을 편집하십시오). 그러나 PATH 하나의 경우 PATH에 너무 많은 디렉토리가 생길 수 있습니다. 이는 항상 좋은 것은 아닙니다 (일부 "foo"명령이 알려지지 않은 경로 중 하나에 존재하고 완전히 다른 것을 수행하는 경우) 일반 사용자가 기대하는 것?)
Olivier Dulac

OP는 경로를 추가하는 더 간결한 방법을 요구했습니다. 이것은 이미 피하려고했던 것보다 훨씬 더 장황하고 오류가 발생하기 쉽습니다.
underscore_d

-1

쉬운 방법이 있습니다! 읽기 쉘 기능 및 경로 변수리눅스 저널 , 2000년 3월 1일으로 스티븐 Collyer

이 함수를 사용하면 bash 환경에서 콜론으로 구분 된 목록 인 새 데이터 유형을 사용할 수 있습니다. PATH 외에도 LOCATE_PATH, MANPATH 및 기타를 조정하고 bash 프로그래밍의 일반 데이터 유형으로 사용합니다. 함수를 사용하여 PATH를 설정하는 방법은 다음과 같습니다.

# Add my bin directory to $PATH at the beginning, so it overrides 
addpath -f -p PATH $HOME/bin

# For Raspberry Pi development (add at end)
addpath -b -p PATH ${HOME}/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

# remove nonexistent directories from PATH
delpath -n -p PATH

# ensure PATH contains unique entries
uniqpath -p PATH

Linux Journal 링크는 "손상됨"으로 표시되므로 Bash Path Functions를 http://pastebin.ubuntu.com/13299528/ 의 .shar 파일에 넣었습니다 .


3
이것들은 어떤 기능입니까? OP는 어떻게 사용합니까? 아마도 그들은 당신의 답변에 깨진 링크로 설명되어 있습니다. 왜냐하면 우리는 항상 답변이 스스로 포함되기를 원합니다. 답변에서 실제 기능을 편집하고 포함하십시오.
terdon

@ terdon : 링크가 나를 위해 작동합니다. 나는 .shar 파일을 pastebin에 넣었습니다 .1K 줄을 여기에 게시하지 않습니다.
waltinator

으악, 나도 지금 일해 댓글을 남길 때가 아닙니다. 어쨌든 내 의견의 요점은 답변에서 외부 리소스와의 연결을 피하려고한다는 것입니다. 우리는 정보가되고 싶어 여기 가 편집, 업데이트 할 수있는 링크의 부패에 영향을받지 않는다.
terdon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.