여기에 대해 알고 싶지 않다고 생각한 모든 것이 있습니다.
요약
Bourne과 같은 쉘 스크립트에서 실행 파일의 경로 이름을 얻으려면 몇 가지주의 사항이 있습니다 (아래 참조).
ls=$(command -v ls)
주어진 명령이 존재하는지 확인하려면 :
if command -v given-command > /dev/null 2>&1; then
echo given-command is available
else
echo given-command is not available
fi
대화식 Bourne과 같은 쉘 프롬프트에서 :
type ls
이 which명령은 C-Shell의 유산으로, Bourne과 같은 껍질에 남겨 두는 것이 좋습니다.
사용 사례
스크립트의 일부로 또는 쉘 프롬프트에서 대화식으로 해당 정보를 찾는 것에는 차이가 있습니다.
쉘 프롬프트에서 일반적인 유스 케이스는 다음과 같습니다 . 이 명령은 이상하게 동작합니다. 올바른 것을 사용하고 있습니까? 입력 할 때 정확히 어떤 일이 발생 mycmd했습니까? 그것이 무엇인지 더 볼 수 있습니까?
이 경우 실제로 명령을 호출하지 않고 명령을 호출 할 때 쉘이 수행하는 작업을 알고 싶습니다.
쉘 스크립트에서는 상당히 다른 경향이 있습니다. 쉘 스크립트에는 명령이 어디에서 무엇을 원하는지 알고 싶은 이유가 없습니다. 일반적으로 알고 싶은 것은 실행 파일의 경로이므로 다른 파일에 대한 경로와 같은 추가 정보를 얻거나 해당 경로의 실행 파일 내용에서 정보를 읽을 수 있습니다.
대화식으로 시스템 에서 사용 가능한 모든my-cmd 명령을 스크립트로 거의 알지 못할 수도 있습니다 .
사용 가능한 대부분의 도구 (대부분의 경우)는 대화식으로 사용하도록 설계되었습니다.
역사
먼저 역사가 조금 있습니다.
70 년대 후반까지 초기 유닉스 쉘에는 기능이나 별명이 없었습니다. 의 기존 실행 파일 만 검색합니다 $PATH. csh1978 주위 도입 별칭 (비록 csh처음 발표 의 2BSD도의 처리 년 5 월 1979 년), 그리고 .cshrc(로, 모든 쉘 쉘을 사용자 정의하는 사용자를 위해 csh읽어 .cshrc도하지 않을 경우 대화 형 스크립트처럼).
Bourne 쉘은 1979 년 초 Unix V7에서 처음 릴리스되었지만 기능 지원은 훨씬 나중에 추가되었지만 (1984 년 SVR2에서), 어쨌든 rc파일 이 없었습니다 ( .profile쉘 자체가 아닌 환경을 구성하는 것입니다 ).
csh Bourne 쉘보다 훨씬 인기가 많았습니다 (Bourne 쉘보다 구문이 심하게 나빴지 만) 대화 형 사용을 위해 더 편리하고 멋진 기능을 많이 추가했습니다.
년 3BSD(1980)하는 whichCSH 스크립트 추가 된 csh실행 파일을 식별하는 데 도움이 사용자, 그리고 당신이로 찾을 수있는 거의 다른 스크립트입니다 which(솔라리스, HP / UX, AIX 또는 Tru64를 같은) 요즘 많은 상용 유닉스에.
이 스크립트는 (를 사용하여 호출하지 않는 한 ~/.cshrc모든 csh스크립트 와 마찬가지로) 사용자를 읽고 csh -f별명 목록과에서를 기반으로 유지 $path되는 배열 에서 제공된 명령 이름을 찾습니다 .csh$PATH
여기 which에서 가장 인기있는 쉘을 csh찾았습니다 (90 년대 중반까지 인기가있었습니다). 이것은 책에 기록되어 여전히 널리 사용되는 주된 이유입니다.
csh사용자의 경우에도 whichcsh 스크립트가 반드시 올바른 정보를 제공하지는 않습니다. ~/.cshrc나중에 프롬프트에서 정의하거나 source다른 csh파일 을 사용하여 정의 할 수 있는 별칭이 아닌에 정의 된 별칭을 가져옵니다 (좋은 아이디어는 아니지만)에서에 PATH정의 될 수 있습니다 ~/.cshrc.
whichBourne 셸에서 해당 명령을 실행하면에에 정의 된 별칭을 찾을 수 ~/.cshrc있지만을 사용하지 않아 별칭 이없는 경우 csh여전히 올바른 답변을 얻을 수 있습니다.
type내장 명령으로 SVR2에서 1984 년까지 유사한 기능이 Bourne 쉘에 추가되지 않았습니다 . 그것이 외부 스크립트와 달리 내장되어 있다는 사실 은 쉘의 내부에 액세스 할 수 있으므로 올바른 정보를 어느 정도 제공 할 수 있음을 의미합니다 .
초기 type명령은 which명령을 찾을 수없는 경우 실패 종료 상태를 리턴하지 않는다는 점 에서 스크립트 와 유사한 문제로 인해 어려움을 겪었습니다 . 또한 실행 파일의 경우와 달리 스크립트에서 사용하기 쉽지 않은 대신 which비슷한 것을 출력합니다 .ls is /bin/ls/bin/ls
유닉스 버전 8 (와일드 버전으로 출시되지 않음) Bourne 쉘의 type기본 이름은으로 변경되었습니다 whatis. 그리고 Plan9 (유닉스의 번 - 될 후계자) 쉘 rc(와 같은 그 유도체 akanga및 es)가 whatis아니라.
80 년대 중반에 개발되었지만 1988 년 이전에 널리 사용되지 않았던 Korn 쉘 (POSIX sh 정의의 기반이되는 서브 세트) csh은 Bourne 쉘 위에 많은 기능 (라인 편집기, 별명 ...)을 추가했습니다. . 자체 옵션 whence을 추가하여 type( -v와 type같은) 여러 옵션을 취했습니다 ( 유사한 자세한 출력 을 제공하고 -p별칭 / 함수가 아닌 실행 파일 만 찾습니다).
AT & T와 버클리 사이의 저작권 문제와 관련하여 혼란과 동시에, 90 년대 초반에 몇 가지 무료 소프트웨어 셸 구현이 나왔습니다. ksh (pdksh)의 퍼블릭 도메인 구현 인 FS에서 bash후원 하는 Almquist 쉘 (ash, BSD에서 Bourne 쉘을 대체하기 위해 재) zsh은 1989 년에서 1991 년 사이에 나왔습니다.
Ash는 Bourne 쉘을 대체하기위한 것이었지만 typeNetBSD 1.3 및 FreeBSD 2.3에서 훨씬 나중에까지 내장 기능이 없었습니다 hash -v. OSF / 1 /bin/sh에는 typeOSF / 1 v3.x까지 항상 0을 리턴 하는 내장 기능이있었습니다. bash추가하지 않은 whence만이 추가 -p하는 옵션 type의 경로를 인쇄하려면을 ( type -p같은 것 whence -p)과 -a보고 모든 일치하는 명령을. tcsh만든 which내장하고 추가 where처럼 행동 명령 bash'들 type -a. zsh그들 모두를 가지고 있습니다.
fish쉘 (2005)는이 type함수로 구현 명령을 사용합니다.
which(이 tcsh가 등 껍질에 많이 사용하지 않을의 내장되면서) 사이에 NetBSD의에서 제거 CSH 스크립트 및 추가 기능 whereis(로 호출하는 경우는 which, whereis같은 행동 which단지에서 실행을 보이는 것을 제외하고 $PATH). OpenBSD와 FreeBSD에서는 which명령 $PATH만 찾는 C로 작성된 것으로 변경되었습니다 .
구현
which구문과 동작이 다른 다양한 Unices에서 수십 가지의 명령 구현이 있습니다.
Linux에서 ( tcsh와 내장 된 것 외에 zsh) 몇 가지 구현이 있습니다. 예를 들어 최근 데비안 시스템에서는에서 명령을 찾는 간단한 POSIX 셸 스크립트입니다 $PATH.
busybox또한이 which명령을 사용합니다.
이 GNU which아마도 가장 사치스러운 일이다. whichcsh 스크립트가 수행 한 작업을 다른 쉘로 확장하려고 시도 합니다. 별명과 함수가 무엇인지 알려 주면 더 나은 답변을 얻을 수 있습니다 (일부 Linux 배포판은 그에 대한 전역 별칭을 설정한다고 생각 bash합니다) .
zsh파일 이름 확장 연산자 및 기록 확장 수정 자 (여기서는 매개 변수 확장에 적용됨) 실행 파일 경로로 확장 할 수 있는 두 개의 연산자 가 있습니다 .= :c
$ print -r -- =ls
/bin/ls
$ cmd=ls; print -r -- $cmd:c
/bin/ls
zsh상기의 zsh/parameters모듈도 같은 명령 해시 테이블하게 commands연관 배열 :
$ print -r -- $commands[ls]
/bin/ls
이 whatis유틸리티 (Unix V8 Bourne 쉘 또는 Plan 9 rc/ 의 유틸리티 제외 es)는 문서 용이므로 실제로는 관련이 없습니다 (whatis 데이터베이스, 즉 매뉴얼 페이지 개요).
whereis또한 추가되었습니다 3BSD과 동시에 which이 작성되었습니다하지만 C,하지 csh동시에, 현재의 환경에 따라 실행, 매뉴얼 페이지와 소스가 아니라에서 조회하는 데 사용됩니다. 다시 말하지만, 그것은 다른 요구에 답합니다.
이제 표준 정면에서 POSIX는 command -v및 -V명령을 지정했습니다 (POSIX.2008까지는 선택 사항이었습니다). UNIX는 type명령을 지정합니다 (옵션 없음). 그건 모든 ( where, which, whence표준에 지정되지 않은)
일부 버전까지, type그리고 command -vLinux Standard Base 사양에서 선택 사항으로, 예를 들어 이전 버전 posh( pdksh둘 다를 기반으로 함 )이없는 이유를 설명 합니다. command -v또한 일부 Bourne 쉘 구현에 추가되었습니다 (Solaris 에서처럼).
오늘 상태
상태는 요즘 그입니다 type및 command -v모든 본쉘 (@jarno에서 언급 한 바와 같이하지만,의주의 / 버그주의에 편재 bash하지 POSIX 모드 또는 Almquist의 일부 자손의 의견은 아래 쉘 때를). tcsh사용하려는 것이 유일한 셸 which(가 전혀 없습니다로 type거기 which내장되어있다).
이외의 껍질에서 tcsh하고 zsh, which한이 별명 또는 함수 같은 이름으로 우리의에서 없다 당신에게 주어진 실행 파일의 경로를 말할 수있다 ~/.cshrc, ~/.bashrc또는 쉘 시작 파일 및 사용자가 정의하지 않는 $PATH당신에 ~/.cshrc. 별명이나 함수가 정의되어 있으면 그것에 대해 말하거나 알려주지 않을 수 있습니다.
주어진 이름으로 모든 명령에 대해 알고 싶다면 이식성이 없습니다. 당신이 사용하는 거라고 where에서 tcsh또는 zsh, type -a에 bash또는 zsh, whence -a경우 ksh93과 다른 쉘에서, 당신은 사용할 수 type와 함께 which -a하는 작동 할 수 있습니다.
추천
실행 파일의 경로 이름 가져 오기
이제 스크립트에서 실행 파일의 경로 이름을 얻으려면 몇 가지주의 사항이 있습니다.
ls=$(command -v ls)
표준 방법이 될 것입니다.
그래도 몇 가지 문제가 있습니다.
- 실행 파일을 실행하지 않고는 경로를 알 수 없습니다. 모든
type, which, command -v... 모든 사용 휴리스틱 경로를 찾을 수 있습니다. $PATH구성 요소를 반복하고 실행 권한이있는 첫 번째 비 디렉토리 파일을 찾습니다. 그러나 셸에 따라 명령을 실행할 때 많은 명령 (Bourne, AT & T ksh, zsh, ash ...)은 시스템 호출이 오류와 함께 반환되지 않을 $PATH때까지 순서대로 실행합니다. execve. 예를 들어 $PATHcontains가 /foo:/bar있고 실행하려는 경우 ls먼저 실행을 시도 /foo/ls하거나 실패하는 경우 /bar/ls. 이제 실행/foo/ls실행 권한이 없지만 유효한 실행 파일이 아닌 다른 많은 이유로 인해 실패 할 수 있습니다. command -v ls에 /foo/ls대한 실행 권한이 있는지 보고 /foo/ls하지만 유효한 실행 파일이 아닌 경우 ls실제로 실행 중일 수 있습니다 ./bar/ls/foo/ls
- 경우
foo내장 명령 또는 함수 또는 별칭이다, command -v foo반환 foo. 일부 껍질처럼 ash, pdksh또는 zsh그것은 또한 반환 할 수 foo있는 경우 $PATH빈 문자열을 포함하고 실행 거기에 foo현재 디렉토리에있는 파일. 이를 고려해야 할 상황이 있습니다. 예를 들어 내장 목록은 셸 구현에 따라 다르며 (예를 들어 mountbusybox 용으로 내장 된 경우도 있음 sh), 예를 들어 bash환경에서 함수를 가져올 수 있습니다.
- 경우
$PATH(일반적으로 상대 경로 구성 요소가 포함 .또는 두 가지 모두 현재 디렉토리를 참조하지만 아무것도 할 수있는 빈 문자열), 쉘에 따라 command -v cmd수도 출력되지 절대 경로. 따라서 달리는 시점에서 얻은 경로 command -v는 cd다른 곳에서 더 이상 유효하지 않습니다 .
- 일화 : 경우 ksh93의 쉘과,
/opt/ast/bin(즉, 정확한 경로는 내가 믿는 다른 시스템에서 다를 수 있지만)이 당신에 $PATH, ksh93의 사용 가능한 몇 가지 추가 내장 명령 (것 chmod, cmp, cat...)를,하지만 command -v chmod돌아갑니다 /opt/ast/bin/chmod그 경로는 '아무튼 경우에도 존재하지 않습니다.
명령이 존재하는지 확인
주어진 명령이 표준으로 존재하는지 확인하려면 다음을 수행하십시오.
if command -v given-command > /dev/null 2>&1; then
echo given-command is available
else
echo given-command is not available
fi
사용하고 싶은 곳 which
(t)csh
에서 csh와 tcsh, 당신은 선택의 여지가 없습니다. 에서 내장 된 tcsh것처럼 괜찮습니다 which. 에서 csh, 이것은 시스템 which명령이 될 것인데, 몇 가지 경우에는 원하는 것을 수행하지 못할 수도 있습니다.
일부 쉘에서만 명령 찾기
사용하는 which것이 합리적 인 경우는 명령 경로를 알고 싶거나 bash, csh( tcsh, dash) 또는 Bourne셸 스크립트 whence -p(예 : ksh또는 zsh) 가 아닌 셸 에서 잠재적 셸 내장 또는 기능을 무시하려는 경우 입니다 , command -ev(같은 yash), whatis -p( rc, akanga) 또는 내장 which(같은 tcsh또는 zsh시스템) which사용 가능하고 아닙니다 csh스크립트.
이러한 조건이 충족되면 다음을 수행하십시오.
echo=$(which echo)
당신에게 첫 번째의 경로 줄 것 echo에서을 $PATH(코너의 경우를 제외)에 관계없이 여부 echo도 쉘 내장 / 별칭 / 기능 여부로 발생합니다.
다른 쉘에서는 다음을 선호합니다.
- zsh을 :
echo==echo나 echo=$commands[echo]또는echo=${${:-echo}:c}
- ksh , zsh :
echo=$(whence -p echo)
- 야쉬 :
echo=$(command -ev echo)
- rc , akanga :
echo=`whatis -p echo`(공백이있는 경로를 조심하십시오)
- 물고기 :
set echo (type -fp echo)
당신이 원하는 모든 경우 참고 실행 하는 echo명령을, 당신은 그것의 경로를 얻을 필요가 없습니다, 당신이 단지 수 :
env echo this is not echoed by the builtin echo
예를 들어 with tcsh를 사용하여 내장 which을 사용 하지 못하게하려면 다음을 수행하십시오.
set Echo = "`env which echo`"
외부 명령이 필요할 때
사용하려는 또 다른 경우 which는 실제로 외부 명령이 필요할 때 입니다. POSIX를 사용하려면 (와 같은 command) 모든 셸 내장 을 외부 명령으로 사용할 수 있어야하지만 불행히도 command많은 시스템 에서 그렇지 않습니다 . 예를 들어, commandLinux 기반 운영 체제 에서 명령 을 찾는 것은 드물지만 대부분은 which명령과 명령이 다릅니다 (다양한 옵션과 동작을 가진 명령이 있음).
외부 명령을 원할 경우 POSIX 쉘을 호출하지 않고 명령을 실행할 수 있습니다.
C 또는 다양한 언어 의 system("some command line"), popen()... 함수는 해당 명령 행을 구문 분석하기 위해 쉘을 호출하므로 system("command -v my-cmd")작동합니다. perl셸 특수 문자 (공백 이외의 문자)가 표시되지 않으면 셸을 최적화 하는 예외가 있습니다 . 이는 백틱 연산자에도 적용됩니다.
$ perl -le 'print system "command -v emacs"'
-1
$ perl -le 'print system ":;command -v emacs"'
/usr/bin/emacs
0
$ perl -e 'print `command -v emacs`'
$ perl -e 'print `:;command -v emacs`'
/usr/bin/emacs
그의 추가 :;위의 힘 perl이 쉘을 호출합니다. 를 사용 which하면 해당 트릭을 사용할 필요가 없습니다.
which에 대한 대부분의 주장 은 대화 형 쉘 컨텍스트를 가정한다고 생각 합니다. 이 질문은 / portability로 태그되었습니다. 그래서 나는이 문맥에서 질문을 ""which에서 주어진 이름의 첫 번째 실행 파일을 찾는 대신에 무엇을 사용해야하는지 "로 해석합니다$PATH. 대부분의which실제 포터블 쉘 스크립트에서 학문적 관심사 인 별칭, 내장 및 기능을 다루는 대부분의 답변과 이유 . 로컬로 정의 된 별칭은 쉘 스크립트를 실행할 때 상속되지 않습니다 (로 소스를 지정하지 않는 한.).