아무도 아직 이것을 언급하지 않은 것에 약간 놀랐지 만 readlink -f
상대 경로를 절대 경로로 변환하고 PATH에 추가하는 데 사용할 수 있습니다 .
예를 들어 Guillaume Perrault-Archambault의 답변을 개선하기 위해
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
PATH="${PATH:+"$PATH:"}$ARG"
fi
done
}
된다
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]
then
if ARGA=$(readlink -f "$ARG") #notice me
then
if [ -d "$ARGA" ] && [[ ":$PATH:" != *":$ARGA:"* ]]
then
PATH="${PATH:+"$PATH:"}$ARGA"
fi
else
PATH="${PATH:+"$PATH:"}$ARG"
fi
fi
done
}
1. 기본 —이 기능은 무엇입니까?
이 readlink -f
명령은 (다른 것들 중에서) 상대 경로를 절대 경로로 변환합니다. 이것은 당신이 같은 것을 할 수 있습니다
$ cd / path / to / my / bin / dir
$ pathappend .
$ echo "$ PATH"
<your_old_path> : / path / to / my / bin / dir
2. 왜 우리는 두 번 PATH에 있는지 테스트합니까?
위의 예를 고려하십시오. 사용자가 말한다면
으로부터 두 번째는 디렉토리
됩니다 . 물론에 없습니다 . 그런데 로 설정한다
(절대 경로 등가 ) 인 이미 . 따라서 우리 는 두 번째로 추가하지 않아야 합니다 .pathappend .
/path/to/my/bin/dir
ARG
.
.
PATH
ARGA
/path/to/my/bin/dir
.
PATH
/path/to/my/bin/dir
PATH
아마도 더 중요한 것은 readlink
그 이름에서 알 수 있듯이 기본 링크의 목적은 심볼릭 링크를보고 포함 된 경로 이름을 읽는 것입니다 (즉, 가리킴). 예를 들면 다음과 같습니다.
$ ls -ld /usr/lib/perl/5.14
-rwxrwxrwx 1 root root Sep 3 2015 /usr/lib/perl/5.14 -> 5.14.2
$ readlink /usr/lib/perl/5.14
5.14.2
$ readlink -f /usr/lib/perl/5.14
/usr/lib/perl/5.14.2
자,이라고 말하고 pathappend /usr/lib/perl/5.14
이미 /usr/lib/perl/5.14
PATH에 있다면, 괜찮습니다. 그대로 그대로 둘 수 있습니다. 하지만, /usr/lib/perl/5.14
당신의 PATH에없는, 우리는 전화를 readlink
얻을 ARGA
=을 /usr/lib/perl/5.14.2
하고 우리는 추가 하는 것이 에 PATH
. 그러나 잠깐 - 당신이 경우 이미 말했다 pathappend /usr/lib/perl/5.14
, 당신은 이미 /usr/lib/perl/5.14.2
, 다시, 우리가에 추가 피하기 위해 그것을 위해 확인해야 PATH에, 그리고 PATH
두 번째.
3. 거래는 if ARGA=$(readlink -f "$ARG")
무엇입니까?
확실하지 않은 경우이 줄은 readlink
성공 여부를 테스트합니다 . 이것은 좋은 방어 적 프로그래밍 연습입니다. 우리가 명령의 출력 사용하고자하는 경우 m를
로 의 일부 명령 N (여기서 m < N )는 명령 여부를 확인하는 신중한 m가 어떤 방법으로 그 실패하고 처리합니다. 나는 그것이 readlink
실패 할 것이라고 생각하지 않는다. 그러나 OS X
와 다른 곳 에서 임의의 파일의 절대 경로를 검색하는 방법에서 논의 된 바와 같이 readlink
, GNU 발명이다. POSIX에는 지정되어 있지 않으므로 Mac OS, Solaris 및 기타 비 Linux 유닉스에서의 가용성에 의문의 여지가 있습니다. (사실, 난 그냥 읽고 코멘트 "라고readlink -f
맥 OS X 10.11.6에 제대로 작동하지 않지만, realpath
상자 밖으로 작동합니다. "그래서, 당신이하지 않는 시스템에 있다면 readlink
, 또는 경우 readlink -f
작동하지 않습니다, 당신이 이것을 수정할 수 있습니다 스크립트를 사용할 수 있습니다 realpath
.) 안전망을 설치하여 코드를 좀 더 이식성있게 만듭니다.
물론, 시스템이 없거나 readlink
(또는 realpath
) 없는 시스템 에서는 할 수 없습니다 .pathappend .
두 번째 -d
테스트 ( [ -d "$ARGA" ]
)는 실제로 불필요합니다. $ARG
디렉토리가 있고 readlink
성공하지만 $ARGA
디렉토리가 아닌 시나리오 는 생각할 수 없습니다 . 방금 첫 번째 if
문장을 복사하여 붙여 넣어 세 번째 문장을 작성하고 -d
테스트를 게으름에서 벗어났습니다.
4. 다른 의견?
네. 여기에있는 다른 많은 답변들과 마찬가지로,이 방법은 각 인수가 디렉토리인지 여부를 테스트하고, 디렉토리가 있으면 처리하며, 그렇지 않으면 무시합니다. 사용중인 경우 (또는하지 않을 수 있습니다) 적합 할 수 pathappend
"만 .
"(같은 파일 .bash_profile
과 .bashrc
) 및 기타 스크립트. 그러나 위의 답변에서 볼 수 있듯이 대화식으로 사용하는 것이 가능합니다. 당신이 할 경우 당신은 매우 당황 할 것이다
$ pathappend /usr/local/nysql/bin
$ mysql
-bash: mysql: command not found
내가 아니라 명령 nysql
에서 내가 말한 것을 알았습니까 ? 그리고 그것은 아무 말도하지 않았습니다. 잘못된 인수를 자동으로 무시 했습니까?pathappend
mysql
pathappend
위에서 말했듯이 오류를 처리하는 것이 좋습니다. 예를 들면 다음과 같습니다.
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ]
then
if [[ ":$PATH:" != *":$ARG:"* ]]
then
if ARGA=$(readlink -f "$ARG") #notice me
then
if [[ ":$PATH:" != *":$ARGA:"* ]]
then
PATH="${PATH:+"$PATH:"}$ARGA"
fi
else
PATH="${PATH:+"$PATH:"}$ARG"
fi
fi
else
printf "Error: %s is not a directory.\n" "$ARG" >&2
fi
done
}