PATH(환경 변수)의 와일드카드 문자

PATH(환경 변수)의 와일드카드 문자

내 홈 디렉토리에 로컬로 많은 앱이 설치되어 있습니다. 전 세계적으로 사용할 수 있도록 다음 PATH위치에 추가했습니다 .bashrc.

PATH="$PATH:/home/user/apps/app1/bin"
PATH="$PATH:/home/user/apps/app2/bin"
PATH="$PATH:/home/user/apps/appn/bin"

새 항목을 모두 추가할 필요가 없도록 하려면 어떻게 설정해야 합니까? 나는 이것을 시도하고 있지만 작동하지 않습니다.

PATH="$PATH:/home/user/apps/*/bin"

노트:루프를 사용하여 추가할 수 있다는 것을 알고 있지만 PATH변수가 너무 커지는 것이 걱정되고 어떻게든 와일드카드를 사용할 수 있는지 알고 싶습니다.

답변1

와일드카드 문자는 $PATH확장되지 않습니다. ~에 따르면배쉬 매뉴얼, 경로는 다음과 같습니다.

콜론으로 구분된 목록목차쉘은 다음에서 명령을 찾습니다.

(내 강조).

반대방향에서 오시는데,명령어 검색 및 실행 부분설명서의 일부는 다음과 같습니다.

이름이 쉘 함수도 내장 함수도 아니고 슬래시를 포함하지 않으면 Bash는 $PATH의 모든 요소를 ​​검색합니다.목차해당 이름의 실행 파일이 포함되어 있습니다.

...(필자의 강조) - 경로 요소의 특별한 처리에 대해서는 언급하지 않고 단지 디렉터리여야 한다는 것입니다(있는 그대로).

bash 변수의 크기 제한이 무엇인지 아직 확실하지 않습니다. 사용 가능한 메모리인 것 같습니다. PATH는 내보낼 필요가 없지만 많은 사람들이 내보낸 경우 다른 환경 변수 및 매개변수와 함께 조정해야 합니다 getconf ARG_MAX(참조:https://unix.stackexchange.com/a/124422/117549). bash는 해시 테이블을 사용하여 이전에 발견된 명령의 위치를 ​​(세션별로) 기억하기 때문에 큰 PATH 디렉토리는 많은 성능 오버헤드를 발생시키지 않아야 합니다.

각 개별 응용 프로그램 디렉터리를 PATH에 추가하는 데 제한(시각적 또는 기술적)이 발생하는 경우 각 응용 프로그램의 모든 파일을 연결할 수 있는 "symlink" 디렉터리를 PATH에 추가하는 것이 좋습니다.

답변2

추가 는 경로가 다음과 같은 디렉터리에서 실행 파일을 검색하는 것을 /home/user/apps/*/bin의미합니다 (완전히 유효한 경로, Unix에서는 문자 1이 파일 이름이나 디렉터리 이름에 사용되는 것을 막을 수 없음 ). 경로가 쓰기 내용과 일치할 때 추가할 수 있습니다. 다음을 사용하는 디렉토리:$PATH/home/user/apps/*/bin*/home/user/apps/*/bin

path+=( /home/user/apps/*/bin(N-/) )

zsh에서 변수는 csh의 배열에 바인딩되며 $PATHglob 한정자를 사용하여 nullglob뿐만 아니라 디렉터리 유형 파일(또는 디렉터리에 대한 기호 링크)로 확장을 제한할 수 있습니다.$path-/N

중복 항목을 제거하기 위해 a를 실행할 수도 있습니다 typeset -U path( U고유 항목의 경우).

where 는 배열로 노출 fish되며 nullglob과 유사한 동작은 다음에서 사용되는 glob에 적용됩니다 .$PATHset

set PATH $PATH /home/user/apps/*/bin

(파일 형식에 국한되지 않음)목차하지만).

POSIXly에서는 언제든지 다음을 수행할 수 있습니다.

for dir in /home/user/apps/*/bin; do
  [ -d "$dir" ] && PATH="${PATH:+$PATH:}$dir"
done

그럼에도 불구하고 나중에 /home/user/apps/에 더 많은 디렉토리가 추가되면 해당 디렉토리는 $PATH.

ksh93에서는 규칙을 사용하여 이러한 마법 같은 효과를 얻을 수 있습니다.

function PATH.get {
  typeset dir
  for dir in ~(N)/home/user/apps/*/bin; do
    [[ :$PATH: = *:"$dir":* || ! -d $dir ]] || PATH=${PATH:+$PATH:}$dir
  done
}

$PATH참조될 때마다 계산되는 값입니다.

zsh에서는 precmd()후크를 사용하거나 각 프롬프트 전에 bash다시 계산을 사용할 수 있습니다 $PROMPT_COMMAND.


¹ 또는 및 NUL 을 제외한 모든 문자 /또는 해당 문제에 대한 문자가 아닌 경우에도 마찬가지입니다.

답변3

이를 위해 몇 가지 솔루션을 사용했습니다.

1. find동적 생성 사용$PATH

이를 위해 유사하지만 약간 수정된 여러 가지 방법을 사용했습니다. 다음과 같은 구조가 있다고 가정해 보겠습니다.

~/apps
├── foo
│   └── bin
├── bar
│   └── bin
└── blah

우리는 할 수 있습니다 ...

ㅏ. 기존 추가응용 프로그램/*/bin/폴더$PATH

이것은 무엇이든 검색합니다쓰레기통/디렉토리$HOME/애플리케이션/*로드할 때 쉘 에 추가하고 $PATH, 없는 디렉토리는 건너뜁니다.쓰레기통/하위 디렉토리.

#.bashrc

bins=$(
    find "$HOME/apps/" -maxdepth 2 -type d -name 'bin' \
        | tr '\n' ':' \
        | sed 's/:$//'
)
export PATH="$bins:$PATH"

생산:

/home/user/apps/foo/bin:/home/user/apps/bar/bin:...

b.추가특정 디렉토리 /*/bin/도착하다$PATH

...각 폴더 여부에 관계없이디렉토리/실제로 하나 있어요쓰레기통/내부의 하위 디렉토리. 이는 위의 디렉토리 구조에 대해애플리케이션/등/빈추가됩니다 $PATH- 존재하지 않더라도!

이는 디렉터리 중 하나가 존재하지 않을 때 유용합니다.지금하나 있다쓰레기통/$PATH하위 디렉터리에 있지만 향후에 있을 가능성이 높으므로 쉘을 생성한 후 쉘에 추가하기 위해 쉘을 다시 로드할 필요 가 없습니다 .

#.bashrc

bins=$(
    find "$HOME/apps/" -maxdepth 1 -type d \
        | sed 's_$_/bin_' \
        | tr '\n' ':' \
        | sed 's/:$//'
)
export PATH="$bins:$PATH"

생산:

/home/user/apps/foo/bin:/home/user/apps/bar/bin:/home/user/apps/blah/bin:...

find 명령은 존재하지 않는 디렉토리를 잠시 찾으려고 시도하므로 이는 성능에 터무니없이 무시할 수 있는 영향을 미칠 수 있습니다.느끼다존재하지 않는 디렉토리를 my 에 추가하는 것은 좋지 않지만 $PATH편의상 이것이 제가 선호하는 옵션입니다.

2. stow실행 파일을 생성하는 데 사용되는 심볼릭 링크

stow바로 이 목적을 위해 만들어졌습니다. 저는 현재 이 설정을 사용하여 모든 도트 파일을 git 저장소에 저장하고 홈 디렉토리에 복사하고 있습니다. :)

다음과 같은 디렉토리 구조가 있는 경우:

.
├── bar
│   └── bin
│       ├── bar-executable-1
│       └── bar-executable-2
├── bin
└── foo
    └── bin
        ├── foo-executable-1
        └── foo-executable-2

당신은 모든 파일을 원한다바/빈/*그리고부자/빈/*다음으로 연결쓰레기통/, 다음을 실행할 수 있습니다.

cd somedir
stow -v --restow --target bin/ --dir bar/ bin
stow -v --restow --target bin/ --dir foo/ bin

--restow참고: 새 심볼릭 링크를 다시 만들기 전에 오래된 심볼릭 링크를 모두 삭제하기 때문에 prune을 사용했습니다.

그러면 다음이 생성됩니다.

somedir
├── bar
│   └── bin
│       ├── bar-executable-1
│       └── bar-executable-2
├── bin
│   ├── bar-executable-1 -> ../bar/bin/bar-executable-1
│   ├── bar-executable-2 -> ../bar/bin/bar-executable-2
│   ├── foo-executable-1 -> ../foo/bin/foo-executable-1
│   └── foo-executable-2 -> ../foo/bin/foo-executable-2
└── foo
    └── bin
        ├── foo-executable-1
        └── foo-executable-2

그런 다음 간단히 추가하면됩니다.특정 디렉토리 /bin/당신을 위한PATH

stow쉽게 사용하세요

만약에

  1. 각 디렉토리 내의 고유 디렉토리신청N디렉토리는 단일입니다.쓰레기통/목차그리고
  2. 컴파일된 내용을 이동할 수 있습니다.쓰레기통/디렉토리 외부의 디렉토리애플리케이션/목차

그런 다음 약간 더 간단한 명령을 사용할 수 있습니다 stow.

/home/user
├── Desktop
├── Documents
├── Pictures
├── Videos
├── apps
│   ├── bar
│   │   └── bin
│   │       ├── bar-executable-1
│   │       └── bar-executable-2
│   └── foo
│       └── bin
│           ├── foo-executable-1
│           └── foo-executable-2
└── bin
cd
stow -v --restow --target ./ --dir apps/ foo bar

이것은 기본적으로 말한다"apps" 폴더에서 "foo" 및 "bar"라는 "패키지"를 찾고 심볼릭 링크를 사용하여 두 패키지의 전체 내용을 현재 디렉터리에 복사합니다.. 그러니까 다 갖고 있으면응용프로그램/foo/그리고앱/바/싱글이다쓰레기통/폴더를 선택하면 다음과 같은 파일이 생성됩니다.쓰레기통/모든 파일에 대한 링크가 포함된 현재 디렉터리의 폴더응용 프로그램/foo/bin/그리고앱/바/빈/.

하지만 다른 파일/폴더가 많으면응용프로그램/foo/그리고앱/바/단 하나를 제외하고쓰레기통/디렉터리를 삭제하면 홈 폴더에도 이 모든 콘텐츠가 다시 생성됩니다. 이는 바람직하지 않을 수 있으므로 첫 번째 예를 따라야 합니다 stow.

https://www.gnu.org/software/stow/manual/html_node/Installing-Packages.html

관련 정보