여기에 대해 알고 싶지 않다고 생각한 모든 것이 있습니다.
요약
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
. csh
1978 주위 도입 별칭 (비록 csh
처음 발표 의 2BSD
도의 처리 년 5 월 1979 년), 그리고 .cshrc
(로, 모든 쉘 쉘을 사용자 정의하는 사용자를 위해 csh
읽어 .cshrc
도하지 않을 경우 대화 형 스크립트처럼).
Bourne 쉘은 1979 년 초 Unix V7에서 처음 릴리스되었지만 기능 지원은 훨씬 나중에 추가되었지만 (1984 년 SVR2에서), 어쨌든 rc
파일 이 없었습니다 ( .profile
쉘 자체가 아닌 환경을 구성하는 것입니다 ).
csh
Bourne 쉘보다 훨씬 인기가 많았습니다 (Bourne 쉘보다 구문이 심하게 나빴지 만) 대화 형 사용을 위해 더 편리하고 멋진 기능을 많이 추가했습니다.
년 3BSD
(1980)하는 which
CSH 스크립트 추가 된 csh
실행 파일을 식별하는 데 도움이 사용자, 그리고 당신이로 찾을 수있는 거의 다른 스크립트입니다 which
(솔라리스, HP / UX, AIX 또는 Tru64를 같은) 요즘 많은 상용 유닉스에.
이 스크립트는 (를 사용하여 호출하지 않는 한 ~/.cshrc
모든 csh
스크립트 와 마찬가지로) 사용자를 읽고 csh -f
별명 목록과에서를 기반으로 유지 $path
되는 배열 에서 제공된 명령 이름을 찾습니다 .csh
$PATH
여기 which
에서 가장 인기있는 쉘을 csh
찾았습니다 (90 년대 중반까지 인기가있었습니다). 이것은 책에 기록되어 여전히 널리 사용되는 주된 이유입니다.
csh
사용자의 경우에도 which
csh 스크립트가 반드시 올바른 정보를 제공하지는 않습니다. ~/.cshrc
나중에 프롬프트에서 정의하거나 source
다른 csh
파일 을 사용하여 정의 할 수 있는 별칭이 아닌에 정의 된 별칭을 가져옵니다 (좋은 아이디어는 아니지만)에서에 PATH
정의 될 수 있습니다 ~/.cshrc
.
which
Bourne 셸에서 해당 명령을 실행하면에에 정의 된 별칭을 찾을 수 ~/.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 쉘을 대체하기위한 것이었지만 type
NetBSD 1.3 및 FreeBSD 2.3에서 훨씬 나중에까지 내장 기능이 없었습니다 hash -v
. OSF / 1 /bin/sh
에는 type
OSF / 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
아마도 가장 사치스러운 일이다. which
csh 스크립트가 수행 한 작업을 다른 쉘로 확장하려고 시도 합니다. 별명과 함수가 무엇인지 알려 주면 더 나은 답변을 얻을 수 있습니다 (일부 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 -v
Linux 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
. 예를 들어 $PATH
contains가 /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
현재 디렉토리에있는 파일. 이를 고려해야 할 상황이 있습니다. 예를 들어 내장 목록은 셸 구현에 따라 다르며 (예를 들어 mount
busybox 용으로 내장 된 경우도 있음 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
많은 시스템 에서 그렇지 않습니다 . 예를 들어, command
Linux 기반 운영 체제 에서 명령 을 찾는 것은 드물지만 대부분은 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
실제 포터블 쉘 스크립트에서 학문적 관심사 인 별칭, 내장 및 기능을 다루는 대부분의 답변과 이유 . 로컬로 정의 된 별칭은 쉘 스크립트를 실행할 때 상속되지 않습니다 (로 소스를 지정하지 않는 한.
).