2009-09-08 4 views

답변

3

뭔가 :

echo "$PATH"|grep -q whatever && echo "found it" 

어디를 검색하는 것입니다 뭐든간에. && 대신 $?을 변수에 넣거나 적절한 if 문을 사용할 수 있습니다.

제한 사항은 다음과 같습니다

  • 은 위의 "빈"이 경로에없는 사실에도 불구하고, 더 큰 경로의 문자열 ("빈"에 일치하는 시도하고 아마 그것을 발견 할 것이다 일치합니다,/빈 그리고는/usr/빈은 ~
  • 은 위의 자동으로 같은 바로 가기를 확장하지 않습니다)입니다

또는 펄 한 라이너를 사용 :

perl -e 'exit(!(grep(m{^/usr/bin$},split(":", $ENV{PATH}))) > 0)' && echo "found it" 

여전히 셸 확장을 수행하지 않지만 하위 문자열이 일치해도 실패하지 않는다는 제한이 있습니다. (위의 내용은 명확하지 않은 경우 "/usr/bin"과 일치 함).

+1

JasonWoof의 대답과 같이 줄과 콜론의 시작/끝과 일치하는 부분 문자열 일치 제한이 적용됩니다. 대부분의 사람들은 할당 할 때 확장 할 수 있지만 (예 :'PATH = "~/bin : $ PATH"), 물결표 확장은 일반적인 문제는 아니지만 필요할 경우 대체 할 수 있습니다. – Cascabel

+2

좋은, 누군가는 3.5 년 후에 이것을 downvoted. 그리고 코멘트를 남기지 않았다. 라메. –

+0

패턴을 콜론으로 묶는 grep 솔루션을 사용하고 있습니다. – elias

102

grep을 사용하면 잔인하며 RE 메타 문자가 포함 된 것을 검색하는 경우 문제가 발생할 수 있습니다. 이 문제는 배쉬의 내장 [[ 명령을 완벽하게 해결 될 수있다 : $ 경로의 확장 및 검색 할 수있는 경로를 모두 전에 콜론을 추가하면 문자열 일치 문제를 해결

if [[ ":$PATH:" == *":$HOME/bin:"* ]]; then 
    echo "Your path is correctly set" 
else 
    echo "Your path is missing ~/bin, you might want to add it." 
fi 

참고; 경로를 이중 인용하면 메타 문자로 인한 문제를 피할 수 있습니다.

+4

'$ HOME/bin '이'$ PATH'의 시작이나 끝에 있다면, 각 끝에 콜론이 없을 것입니다. –

+8

귀하의 이의 제기를 이해하고 있는지 잘 모르겠습니다. 예를 들어 $ PATH가/usr/bin :/bin :/usr/sbin :/sbin :/home/fred/bin이면 ":/usr/bin :/bin :/usr/sbin :/sbin :/home/fred/bin : "*와 일치합니다.":/home/fred/bin : "* 괜찮습니다. –

+6

네 말이 맞아. 나는 "$ PATH"주위에 콜론의 역할을 보지 못했습니다. 죄송합니다. –

10

여기 grep없이 그것을 할 방법은 다음과 같습니다 여기

if [[ $PATH == ?(*:)$HOME/bin?(:*) ]] 

의 핵심은 콜론을 만드는 것입니다 및 ?() 구조를 사용하여 선택 와일드 카드. 이이 양식에서 메타 문자에 문제가 될,하지만 당신은 따옴표를 포함 할 경우이 그들이가는 곳입니다 안 :이 경기 연산자 (=~) 그래서 구문을 사용하여 그것을 할 수있는 또 다른 방법은

if [[ "$PATH" == ?(*:)"$HOME/bin"?(:*) ]] 

grep 년대 같다 :

if [[ "$PATH" =~ (^|:)"${HOME}/bin"(:|$) ]] 
+0

'? (: *)'는 [확장 glob] (https://mywiki.wooledge.org/glob#extglob) 패턴이며 대부분의 플랫폼에서 별도로 명시 적으로 활성화해야합니다 ('shopt -s extglob'). – tripleee

0

$PATH는 디렉토리리스트를 설명 : 의해 분리 문자열리스트이다. 디렉토리는 /으로 구분 된 문자열 목록입니다. 두 개의 다른 문자열은 같은 디렉토리 (예 : $HOME~ 또는 /usr/local/bin/usr/local/bin/)를 가리킬 수 있습니다. 따라서 우리는 우리가 비교/점검하고자하는 규칙을 고쳐야합니다. 필자는 실제 디렉토리가 아닌 전체 문자열을 비교/검사 할 것을 제안하지만 중복을 제거하고 후행 /을 제거합니다.

먼저 제거 중복 및 $PATH에서 / 후행 :

 
echo $PATH | tr -s/| sed 's/\/:/:/g;s/:/\n/g' 

지금 $d가 검사 할 디렉토리를 포함 같아요. 그런 다음 이전 명령을 파이프하여 $d$PATH에 확인하십시오.

 
echo $PATH | tr -s/| sed 's/\/:/:/g;s/:/\n/g' | grep -q "^$d$" || echo "missing $d" 
0

디렉토리가 현재 PATH에 나열되면보고 할 다음 쉘 기능을 작성했습니다. 이 함수는 POSIX와 호환되며 Dash 및 Bash와 같은 호환 쉘 (Bash 특정 기능에 의존하지 않고)에서 실행됩니다.

상대 경로를 절대 경로로 변환하는 기능이 포함되어 있습니다. 이 경우 readlink 또는 realpath 유틸리티를 사용하지만 제공된 디렉토리에 .. 또는 경로의 구성 요소로 다른 링크가없는 경우에는 이러한 도구가 필요하지 않습니다. 이 외에도 함수는 쉘 외부의 프로그램을 필요로하지 않습니다.

# Check that the specified directory exists – and is in the PATH. 
is_dir_in_path() 
{ 
    if [ -z "${1:-}" ]; then 
    printf "The path to a directory must be provided as an argument.\n" >&2 
    return 1 
    fi 

    # Check that the specified path is a directory that exists. 
    if ! [ -d "$1" ]; then 
    printf "Error: ‘%s’ is not a directory.\n" "$1" >&2 
    return 1 
    fi 

    # Use absolute path for the directory if a relative path was specified. 
    if command -v readlink >/dev/null ; then 
    dir="$(readlink -f "$1")" 
    elif command -v realpath >/dev/null ; then 
    dir="$(realpath "$1")" 
    else 
    case "$1" in 
     /*) 
     # The path of the provided directory is already absolute. 
     dir="$1" 
     ;; 
     *) 
     # Prepend the path of the current directory. 
     dir="$PWD/$1" 
     ;; 
    esac 
    printf "Warning: neither ‘readlink’ nor ‘realpath’ are available.\n" 
    printf "Ensure that the specified directory does not contain ‘..’ in its path.\n" 
    fi 

    # Check that dir is in the user’s PATH. 
    case ":$PATH:" in 
    *:"$dir":*) 
     printf "‘%s’ is in the PATH.\n" "$dir" 
     return 0 
     ;; 
    *) 
     printf "‘%s’ is not in the PATH.\n" "$dir" 
     return 1 
     ;; 
    esac 
} 

:$PATH:를 사용하는 제품은 원하는 경로가 PATH에서 첫 번째 또는 마지막 항목이있는 경우, 패턴 일치는 것을 보장한다. 이 영리한 트릭은 this answer by Glenn Jackman on Unix & Linux을 기반으로합니다.

0

grep과 같은 외부 유틸리티를 사용할 필요가 전혀 없습니다. 여기 내가 사용하고있는 것은 Bourne 쉘의 레거시 버전까지도 이식 가능해야합니다.

case :$PATH: # notice colons around the value 
    in *:$HOME/bin:*) ;; # do nothing, it's there 
    *) echo "$HOME/bin not in $PATH" >&2;; 
esac 
관련 문제