실행 파일의 경로를 찾거나 Unix 셸에 명령 이름을 입력하면 어떤 일이 발생하는지 확인할 때 “다양한 유틸리티 ( which
, type
, command
, whence
, where
, whereis
, whatis
, hash
등).
which
를 피해야한다는 말을 자주 듣습니다. 그 이유는 무엇입니까? 대신 무엇을 사용해야합니까?
댓글
답변
여기에 대해 알고 싶지 않을 것이라고 생각한 적이없는 모든 것이 있습니다.
요약
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
? 그것이 무엇인지 더 자세히 살펴볼 수 있습니까?
이 경우 실제로 명령을 호출하지 않고 명령을 호출 할 때 쉘이 수행하는 작업을 알고 싶습니다.
쉘 스크립트에서는 상당히 다른 경향이 있습니다. 쉘 스크립트에서는 명령을 실행하기 만하면 명령이 어디에 있는지 또는 무엇인지 알고 싶은 이유가 없습니다. 일반적으로 알고 싶은 것은 실행 파일의 경로이므로 여기에서 더 많은 정보를 얻을 수 있습니다 (예 : 다른 파일에 대한 경로 또는 해당 경로에있는 실행 파일의 내용에서 정보를 읽을 수 있음).
대화식으로 시스템에서 사용할 수있는 모든 명령에 대해 스크립트에서 거의 알 수없는 경우도 있습니다.
p>
대부분의 사용 가능한 도구 (대부분의 경우)는 대화식으로 사용하도록 설계되었습니다.
역사
역사를 먼저 살펴 보겠습니다.
70 년대 후반까지 초기 Unix 셸에는 기능이나 별칭이 없었습니다. $PATH
에서 실행 파일의 전통적인 조회 만 가능합니다. csh
는 1978 년경에 별칭을 도입했지만 csh
는 2BSD
출시 되었습니다. / div>, 1979 년 5 월), 사용자가 셸을 사용자 지정할 수 있도록 .cshrc
처리 (모든 셸, csh
, .cshrc
는 스크립트처럼 대화 형이 아닐 때도 읽습니다. 나중에 (SVR2의 경우 1984 년) 어쨌든 rc
파일이 없었습니다 (.profile
는 셸이 아닌 환경을 구성하는 것입니다. 그 자체 ).
csh
는 Bourne 셸보다 훨씬 더 인기를 얻었습니다 (하지만 구문이 Bourne shell) 대화 형 사용을 위해 더 편리하고 멋진 기능을 많이 추가했습니다.
3BSD
(1980)에서 which
csh 스크립트 가 csh
사용자를 위해 추가되어 실행 파일을 식별하는 데 도움이되었으며 ” 오늘날 많은 상용 Unices (예 : Solaris, HP / UX, AIX 또는 Tru64)에서 사용됩니다.
이 스크립트는 사용자의 ~/.cshrc
를 읽습니다. (모든 csh
스크립트와 마찬가지로 csh -f
로 호출하지 않는 한), 별칭 목록에서 제공된 명령 이름을 조회합니다. $path
(csh
가 $PATH
를 기반으로 유지하는 배열).
여기 있습니다. which
는 당시 가장 인기있는 셸로 1 위를 차지했습니다 (그리고 csh
는 중반까지 여전히 인기가있었습니다. 90 년대), 이것이 책에 문서화되고 여전히 널리 사용되는 주된 이유입니다.
csh
사용자의 경우에도 which
csh 스크립트가 반드시 올바른 정보. 나중에 프롬프트에서 정의한 별칭이 아니라 ~/.cshrc
에 정의 된 별칭을 가져옵니다. 예를 들어 source
다른 csh
파일 및 (좋은 생각은 아니지만) PATH
는 ~/.cshrc
.
Bourne 셸에서 which
명령을 실행하면 여전히 ~/.cshrc
에 정의 된 별칭을 조회하지만 csh
를 사용하지 않아 계정이없는 경우에도 올바른 답을 얻을 수 있습니다.
비슷한 기능이 추가되지 않았습니다. type
내장 명령을 사용하여 SVR2에서 1984 년까지 Bourne 쉘. (외부 스크립트와는 반대로) 내장되어 있다는 사실은 쉘 내부에 액세스 할 수 있으므로 올바른 정보를 (어느 정도까지) 제공 할 수 있다는 것을 의미합니다.
초기 type
명령은 다음과 같은 경우 실패 종료 상태를 반환하지 않는다는 점에서 which
스크립트와 유사한 문제가 발생했습니다. 명령을 찾을 수 없습니다. 또한 실행 파일의 경우 which
와 달리 iv id = “대신 ls is /bin/ls
와 같은 결과를 출력합니다. 1ef2ca896a “>
로 인해 스크립트에서 사용하기가 더 쉬워졌습니다.
Unix 버전 8″(야생으로 출시되지 않음) Bourne 쉘에는 “s type
builtin의 이름이 whatis
로 변경되었습니다. Plan9 (한때 Unix의 후계자) 쉘 rc
(및 akanga
및 es
)와 같은 파생 상품에도 whatis
가 있습니다.
Korn 쉘 ( POSIX sh
정의 기반) 80 년대 중반에 개발되었지만 1988 년 이전에는 널리 사용되지 않았으며 csh
기능 ( 라인 편집기, 별칭 …) Bourne 쉘 위에 있습니다. 여러 옵션 (-v
div)을 사용하는 자체 whence
내장 (type
외에)을 추가했습니다. >는 type
와 같은 자세한 출력을 제공하고 -p
는 실행 파일 만 찾습니다 (별칭 / 함수 아님 …). .
AT & T와 Berkeley 간의 저작권 문제와 관련된 혼란과 함께 몇 가지 자유 소프트웨어 셸 구현이 나왔습니다. 80 년대 후반 90 년대 초반에모든 Almquist 셸 (ash
, BSD의 Bourne 셸 대체), ksh
(pdksh
), bash
(FSF 후원), 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
를 추가하지 않았지만 옵션을 type
로 설정하여 경로를 인쇄합니다 (type -p
는 whence -p
) 및 -a
는 일치하는 명령을 모두 보고합니다. tcsh
는 which
를 내장하고 iv id = “ff5888723f처럼 작동하는 where
명령을 추가했습니다. “> “의 type -a
. zsh
에 모두 있습니다.
fish
셸 (2005)에는 type
명령이 함수로 구현되어 있습니다.
which
csh 스크립트는 NetBSD (tcsh에 내장되어 있고 다른 쉘에서는 많이 사용되지 않음)에서 제거되었으며 whereis
에 추가 된 기능 (which
, whereis
는 iv id = “00879d7bee”에서 실행 파일 만 조회한다는 점을 제외하고는 which
처럼 작동합니다. > ). OpenBSD 및 FreeBSD에서 which
도 $PATH
에서만 명령을 조회하는 C로 작성된 것으로 변경되었습니다. .
구현
which
공동 구현에는 수십 가지가 있습니다. mmand 구문과 동작이 다른 다양한 Unices에서.
Linux (tcsh
및 zsh
의 기본 제공 항목 제외) ) 우리는 몇 가지 구현을 찾습니다. 예를 들어 최신 Debian 시스템에서는 “$PATH
에서 명령을 찾는 간단한 POSIX 셸 스크립트입니다.
busybox
에도 which
명령이 있습니다.
GNU
which
는 아마도 가장 사치스러운 것일 것입니다. which
csh 스크립트가 수행 한 작업을 다른 셸로 확장하려고합니다. 별칭과 함수가 무엇인지 알려줄 수 있습니다. 더 나은 대답입니다 (일부 Linux 배포판에서는 bash
에 대해 전역 별칭을 설정한다고 생각합니다).
zsh
에는 실행 파일 경로로 확장 할 수있는 두 개의 연산자 가 있습니다. =
파일 이름 확장 연산자와 :c
기록 확장 수정 자 (여기서는 매개 변수 확장 에 적용됨) :
$ print -r -- =ls /bin/ls $ cmd=ls; print -r -- $cmd:c /bin/ls
zsh
, 모듈은 명령 해시 테이블을 commands
연관 배열로 만듭니다 :
$ print -r -- $commands[ls] /bin/ls
whatis
유틸리티 (Unix V8 Bourne 쉘 또는 Plan 9의 유틸리티 제외 rc
/ es
)는 문서 용으로 만 사용되므로 실제로 관련이 없습니다 (whatis 데이터베이스, 즉 man 페이지 시놉시스).
whereis
도 마찬가지입니다. C
로 작성되었지만 which
와 동시에 3BSD
에 추가되었습니다. 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
가 모두 어디에나 있다는 것입니다. Bourne과 같은 셸 (@jarno에서 언급했듯이 POSIX 모드가 아닌 경우 bash
의 경고 / 버그 또는 주석 아래 Almquist 셸의 일부 하위 항목). tcsh
는 which
를 사용하려는 유일한 셸입니다 (type
거기에 있고 which
가 내장되어 있습니다).
tcsh
및 , which
는
,~/.bashrc
또는 모든 셸 시작 파일이며 iv id에$PATH
를 정의하지 않습니다. = “c92e1ab12d”> . 별칭 또는 함수가 정의되어 있으면 이에 대해 알려주거나 말하지 않을 수도 있고 잘못된 것을 알려줄 수도 있습니다.
알고 싶은 경우 주어진 이름의 모든 명령에 대해서는 이식성이 없습니다. tcsh
또는 zsh
, iv id = “9a534a3bbe”에서 where
를 사용합니다. > in bash
또는 zsh
, whence -a
in ksh93 및 기타 셸 , 작동 할 수있는 which -a
와 함께 type
를 사용할 수 있습니다.
권장 사항
실행 파일의 경로 이름 가져 오기
이제 스크립트에서 실행 파일의 경로 이름을 가져 오려면 몇 가지주의 사항이 있습니다.
ls=$(command -v ls)
이 작업을 수행하는 표준 방법이 될 것입니다.
하지만 몇 가지 문제가 있습니다.
- 실행 파일을 실행하지 않고는 실행 파일의 경로를 알 수 없습니다.
type
,which
,command -v
… 모두 휴리스틱을 사용하여 경로를 찾습니다. . 그들은$PATH
구성 요소를 반복하고 실행 권한이있는 첫 번째 비 디렉토리 파일을 찾습니다. 그러나 depe 셸에서 명령을 실행할 때 많은 명령 (Bourne, AT & T ksh, zsh, ash …)은 명령을 다음 순서대로 실행합니다.$PATH
execve
시스템 호출이 오류와 함께 반환되지 않을 때까지. 예를 들어$PATH
에/foo:/bar
가 포함되어 있고ls
를 실행하려는 경우 먼저/foo/ls
를 실행하거나 실패하는 경우/bar/ls
. 이제/foo/ls
실행이 “실행 권한이 없지만 유효한 실행 파일이 아닌 다른 여러 이유로 인해 실패 할 수 있습니다.”command -v ls
는/foo/ls
에 대한 실행 권한이 있지만 iv id를 실행하는 경우/foo/ls
를보고합니다. = “d15a078f48”> 는/foo/ls
가 유효한 실행 파일이 아닌 경우 실제로/bar/ls
를 실행할 수 있습니다. -
foo
가 내장 또는 함수 또는 별칭 인 경우command -v foo
는foo
를 반환합니다.ash
,pdksh
또는zsh
와 같은 일부 셸에서는$PATH
에 빈 문자열이 포함되고 “현재 디렉토리에 실행 가능한foo
파일이있는 경우. 이를 고려해야하는 몇 가지 상황이 있습니다. 예를 들어 내장 목록은 셸 구현에 따라 다릅니다 (예 :mount
는 때때로 busybox에 내장되어 있음)sh
), 예를 들어bash
는 환경에서 함수를 가져올 수 있습니다. - if
$PATH
에는 쉘에 따라 상대 경로 구성 요소 (일반적으로.
또는 둘 다 현재 디렉토리를 참조하지만 무엇이든 될 수있는 빈 문자열)가 포함됩니다.command -v cmd
는 절대 경로를 출력하지 않을 수 있습니다. 따라서 는cd
다른 곳에서 더 이상 유효하지 않습니다. - 필수 : (정확한 경로는 내가 믿는 시스템마다 다를 수 있음)는
$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)
첫 번째 iv id의 경로를 제공합니다. $PATH
의 = “46435c0fe2”> (코너 케이스 제외), echo
도 셸인지 여부에 관계없이 builtin / alias / function 여부.
다른 셸에서는 다음을 선호합니다.
- zsh :
echo==echo
또는echo=$commands[echo]
또는echo=${${:-echo}:c}
- ksh , zsh :
echo=$(whence -p echo)
- yash :
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
예를 들어, tcsh
를 사용하면 내장 which
가 사용되지 않도록 방지합니다.
set Echo = "`env which echo`"
외부 명령이 필요한 경우
which
를 사용할 수있는 또 다른 경우는 실제로 필요한 경우입니다. 외부 명령입니다. POSIX에서는 모든 셸 내장 (예 : command
)을 외부 명령으로도 사용할 수 있어야하지만 안타깝게도 command
에는 해당되지 않습니다. 예를 들어 Linux 기반 운영 체제에서는 command
명령을 찾기가 드물지만 대부분은 which
명령 (옵션과 동작은 다르지만)
외부 명령이 필요한 경우 POSIX 셸을 호출하지 않고 명령을 실행할 수있는 위치에 있습니다.
system("some command line")
, popen()
… C 또는 다양한 언어의 함수는 셸을 호출하여 해당 명령 줄을 구문 분석하므로 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
를 사용하면 그 속임수를 사용할 필요가 없습니다.
댓글
- @Joe,
which
는 많은 상용 Unices의csh
스크립트입니다. 그 이유는 역사적이며 ‘ 내가 역사를 제공 한 이유이므로 사람들은 그것이 어디에서 왔는지, 사람들이 사용하는 데 익숙해 진 이유와 실제로 그곳에있는 이유를 이해합니다. ‘를 사용해야 할 이유가 없습니다. 그리고 예, 어떤 사람들은 (t) csh를 사용합니다. 아직 모든 사람이 Linux를 사용하는 것은 아닙니다. - 이 게시물을 읽은 후 답변에 대한 많은 컨텍스트를 찾았지만 답변 자체는 찾지 못했습니다.이 게시물의 어디에
which
를 사용하려는 것과는 달리 사용하지 않는 이유가 실제로 설명되어 있습니다.which
할 일,which
의 역사,which
의 구현, 관련 작업을 수행하기위한 기타 명령 또는 실제로 사용해야하는 이유which
? 다른 명령이 더 나은 이유는 무엇입니까?which
와 다른 점은 무엇입니까? 그 함정을 어떻게 피합니까? 이 답변은 실제로which
의 문제보다 대안 문제에 더 많은 단어를 사용합니다. -
command
가 설명되어 있습니다. POSIX. - @St é phaneChazelas
touch /usr/bin/mytestfile
로 새 파일을 만든 다음command -v mytestfile
, 경로를 제공합니다 (반면which mytestfile
는 제공하지 않음). - @jarno, 오 예, 당신은 ‘ 맞습니다.
bash
는 실행 가능한 파일을 찾을 수없는 경우 ‘ 실행할 수없는 파일을 확인하므로 ‘ s ” OK ” (실제로는command -v
/type
는 ‘mytestfile
그러나dash
동작은 마치 실행 불가능한cmd
버그가 있습니다. 실행 파일보다 먼저command -v
는 실행 불가능한 것을 반환하고cmd
는 실행 가능한 것을 실행합니다 (잘못된 하나도 해시 됨). FreeBSDsh
(또한ash
를 기반으로 함)에는 동일한 버그가 있습니다. zsh, yash, ksh, mksh, bash as sh는 괜찮습니다.
답변
사용하고 싶지 않음 which
는 이미 설명했지만 다음은 which
가 실제로 실패하는 몇 가지 시스템에 대한 몇 가지 예입니다.
Bourne 유사 셸에서 which
의 출력을 type
의 출력과 비교합니다 (type
셸 내장이므로 “명령을 호출하는 방법을 알려주는 셸이기 때문에”실측 정보 “를 의미합니다.
많은 경우가 코너 케이스이지만 which
/ type
는 코너 케이스에서 자주 사용됩니다 (답을 찾기 위해 다음과 같은 예상치 못한 동작 : 이 명령이 왜 그렇게 동작 하는가? ).
대부분의 시스템, 대부분의 Bourne 유사 쉘 : 함수
가장 명백한 경우는 함수입니다.
$ type ls ls is a function ls () { [ -t 1 ] && set -- -F "$@"; command ls "$@" } $ which ls /bin/ls
이유는 which
가 실행 파일에 대해서만보고하고 때로는 함수가 아닌 별칭 (항상 사용자 셸의 별칭은 아님)에 대해서만보고하기 때문입니다.
맨 페이지가 깨진 GNU ($@
를 인용하는 것을 잊었 기 때문에) 함수를보고하는 방법에 대한 예제도 있지만 별칭은 “셸 구문 파서를 구현하지 않기 때문에”쉽게 속일 수 있습니다.
$ which() { (alias; declare -f) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot "$@";} $ f() { echo $"\n}\ng ()\n{ echo bar;\n}\n" >> ~/foo; } $ type f f is a function f () { echo " } g () { echo bar; } " >> ~/foo } $ type g bash: type: g: not found $ which f f () { echo " } $ which g g () { echo bar; }
대부분의 시스템, 대부분의 Bourne 유사 셸 : 내장 h2>
또 다른 명백한 경우는 내장 또는 키워드입니다. which
는 외부 명령이 셸에 어떤 내장 기능이 있는지 알 방법이 없기 때문입니다 (그리고 , bash
또는 ksh
는 내장 기능을 동적으로로드 할 수 있습니다.) :
$ type echo . time echo is a shell builtin . is a shell builtin time is a shell keyword $ which echo . time /bin/echo which: no . in (/bin:/usr/bin) /usr/bin/time
(which
가 내장 된 zsh
에는 적용되지 않음)
Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5. 1 및 기타 :
$ csh % which ls ls: aliased to ls -F % unalias ls % which ls ls: aliased to ls -F % ksh $ which ls ls: aliased to ls -F $ type ls ls is a tracked alias for /usr/bin/ls
왜냐하면 대부분의 상용 Unices에서 which
(원래 구현에서와 같이 3BSD에서)는 ~/.cshrc
를 읽는 csh
스크립트입니다. 보고 할 별칭은 현재 정의한 별칭과 실제로 사용중인 셸에 관계없이 여기에 정의 된 별칭입니다.
HP / UX 또는 Tru64 :
% echo "setenv PATH /bin:/usr/bin" >> ~/.cshrc % setenv PATH ~/bin:/bin:/usr/bin % ln -s /bin/ls ~/bin/ % which ls /bin/ls
(Solaris 및 AIX 버전은 ~/.cshrc
div를 읽기 전에 $path
를 저장하여이 문제를 해결했습니다. > 명령을 찾기 전에 복원)
$ type "a b" a b is /home/stephane/bin/a b $ which "a b" no a in /usr/sbin /usr/bin no b in /usr/sbin /usr/bin
또는 :
$ d="$HOME/my bin" $ mkdir "$d"; PATH=$PATH:$d $ ln -s /bin/ls "$d/myls" $ type myls myls is /home/stephane/my bin/myls $ which myls no myls in /usr/sbin /usr/bin /home/stephane/my bin
(물론 csh
스크립트이므로 공백이 포함 된 인수와 함께 작동 할 것으로 기대할 수 없습니다 …)
CentOS 6.4, bash
$ type which which is aliased to `alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde" $ alias foo=": "|test|"" $ which foo alias foo=": "|test|"" /usr/bin/test $ alias $"foo=\nalias bar=" $ unalias bar -bash: unalias: bar: not found $ which bar alias bar="
해당 시스템에는 GNU which
명령을 래핑하는 시스템 전체에 정의 된 별칭이 있습니다.
가짜 출력은 which
가 bash
“의 alias
그러나 제대로 구문 분석하는 방법을 모르고 휴리스틱을 사용합니다 (한 줄에 하나의 별칭, |
, , &
…)
CentOS에서 가장 나쁜 점은 zsh
가 완벽하게 훌륭한 which
내장 명령이지만 CentOS는 GNU which
의 작동하지 않는 별칭으로 대체하여이를 깨뜨 렸습니다.
Debian 7.0, ksh93 :
(많은 셸이있는 대부분의 시스템에 적용됨)
$ unset PATH $ which which /usr/local/bin/which $ type which which is a tracked alias for /bin/which
Debian의 경우 /bin/which
는 /bin/sh
스크립트입니다. 제 경우에는 sh
가 dash
이지만 bash
.
설정되지 않은 PATH
는 PATH
조회를 비활성화하는 것이 아니라 시스템의 기본 경로 는 안타깝게도 Debian에서는 아무도 동의하지 않습니다 (dash
및 bash
에는 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
, zsh
에는 /bin:/usr/bin:/usr/ucb:/usr/local/bin
, ksh93
에는 , mksh
에는 /usr/bin:/bin
($(getconf PATH)
),
(예 : env
)에는 :/bin:/usr/bin
가 있습니다 (예, 현재 디렉토리를 먼저 확인합니다!). .
which
가 dash
“의 기본 iv id를 사용하기 때문에 위의 오류가 발생하는 이유는 무엇입니까? ksh93
“와 다른 =”ac187d6c45 “>
아니요 다음을보고하는 GNU which
를 사용하면 더 좋습니다.
which: no which in ((null))
(흥미롭게도 실제로 /usr/local/bin/which
는 실제로 akanga
와 함께 제공되는 akanga
스크립트입니다 (rc
셸 파생 (기본 PATH
는 /usr/ucb:/usr/bin:/bin:.
))
bash, 모든 시스템 :
$ PATH=$HOME/bin:/bin $ ls /dev/null /dev/null $ cp /bin/ls bin $ type ls ls is hashed (/bin/ls) $ command -v ls /bin/ls $ which ls /home/chazelas/bin/ls
또한 hash
를 수동으로 호출 한 후 :
$ type -a which which is /usr/local/bin/which which is /usr/bin/which which is /bin/which $ hash -p /bin/which which $ which which /usr/local/bin/which $ type which which is hashed (/bin/which)
이제 which
및 때때로 type
실패 :
$ mkdir a b $ echo "#!/bin/echo" > a/foo $ echo "#!/" > b/foo $ chmod +x a/foo b/foo $ PATH=b:a:$PATH $ which foo b/foo $ type foo foo is b/foo
이제 일부 셸 :
$ foo bash: ./b/foo: /: bad interpreter: Permission denied
다른 사용자와 함께 :
$ foo a/foo
which
도 type
는 b/foo
가 b를 수행 할 수 없음을 미리 알 수 있습니다. e 실행. iv id = “488253cbe9를 호출 할 때 bash
, ksh
또는 yash
와 같은 일부 셸 “> 는 실제로 b/foo
를 실행하고 오류를보고하는 반면 다른 것 (예 : zsh
, ash
, csh
, Bourne
, tcsh
)는 a/foo
execve()
시스템 호출이 b/foo
에서 실패한 경우
댓글
-
mksh
는 실제로 기본$PATH
에 대해 다른 것을 사용합니다. , 운영 체제의 컴파일 타임 상수_PATH_DEFPATH
가 사용되고 (가장 일반적으로 BSD에서)confstr(_CS_PATH, …)
가 사용됩니다 (POSIX). 둘 다 존재하지 않거나 실패하면/bin:/usr/bin:/sbin:/usr/sbin
가 사용됩니다. - 첫 번째 예에서는
ls
사용하는 기능입니다 g PATH의ls
. 그리고which
는/usr/bin/ls
또는/usr/local/bin/ls
중 어느 것이 사용되는지 알려줍니다. ‘ ” 어떤 것을 사용하지 않는지 ” …. li> - @rudimeier,
which ls
는ls
여부에 관계없이/bin/ls
를 제공합니다. div> 함수는/bin/ls
또는/opt/gnu/bin/ls
또는dir
를 호출하거나 전혀 호출하지 않습니다. IOW,which
(구현되는 IMMV)는 관련없는 무언가를 제공합니다 - @St é phaneChazelas. 아니, 아니. 내
ls
가 함수라는 것을 이미 알고 있습니다 . 내ls
함수가PATH
div에서ls
를 호출하고 있다는 것을 알고 있습니다 . >. 이제which
가 파일의 위치를 알려줍니다. 단 하나의 사용 사례 : “이 명령으로 내 셸이 수행하는 작업. “이 사용 사례의 경우which
가 잘못되었습니다.그러나 (GNU)which
가 정확히 맞는 다른 사용 사례가 있습니다. - @rudimeter,
which
구현. 일부는 별칭을 ‘ 알려줍니다 (별칭이 구성되어 있거나 집에~/.cshrc
이러한 별칭), 일부는 경로를 제공하지만 일부 조건에서는 잘못된 경로를 제공합니다.sh -c 'command -v ls'
, 완벽하지는 않지만 여전히 다양한 요구 사항에 대한 올바른 답변을 제공 할 가능성이 높습니다 (또한 표준 임).
답변
Stephane이 언급하지 않은 것으로 보이는 한 가지는 which
가 쉘의 경로 해시 테이블에 대해 전혀 모릅니다. 이로 인해 실제로 실행 된 내용을 나타내지 않는 결과가 반환되어 디버깅에 효과가 없습니다.
Answer
which
에 대한 근거없는 배싱은 누구에게나 유용하지 않기 때문에 의심하지 않는 사용자에게이 질문이 권장 될 때 일반적으로 움찔합니다.
If which
는 유닉스 모토에 따라 잘 작동하고 일부 작업에 대한 올바른 답을 제공합니다. 한 가지만 잘 수행 , 왜 which
가 금지되어 있습니까?
그러면 어떤 것이 잘 작동하고 특정 작업을 잘 수행하는지 질문해야합니다.
하나는 데비안의 / bin / which에있는 외부 유틸리티입니다. 경로에 지정된 이름의 실행 파일 만 나열하는 것이 목표 인 쉘 스크립트입니다. which
가 의도 한 목표를 올바르게 수행한다고 믿습니다. 별명도, 기능도, 쉘에서 아무것도로드하지 않고 PATH에 지정된 이름의 첫 번째 (또는 모든) 실행 파일 만 나열합니다. 주어진 것과 같은 이름의 파일을 찾았다는 의미 는 사용자가 그녀 (그)가 알아 내야하는 것입니다. self.
예, 다른 which
구현에는 특정 문제가있을 수 있으며 일반적으로 발생합니다.
답변
우리는 종종 피해야한다는 말을 듣습니다. 왜? 대신 무엇을 사용해야합니까?
그 말은 들어 본 적이 없습니다. 구체적인 예를 제공하세요. which
의 출처 인 Linux 배포 및 설치된 소프트웨어 패키지에 대해 걱정하겠습니다.
SLES 11.4 x86-64
tcsh 버전 6.18.01 :
> which which which: shell built-in command.
bash 버전 3.2-147 :
> which which /usr/bin/which > which -v GNU which v2.19, Copyright (C) 1999 - 2008 Carlo Wood. GNU which comes with ABSOLUTELY NO WARRANTY; This program is free software; your freedom to use, change and distribute this program is protected by the GPL.
which
는 util-linux Linux 운영 체제의 일부로 사용하기 위해 Linux Kernel Organization에서 배포 한 표준 패키지입니다. 또한 이러한 다른 파일도 제공합니다.
/bin/dmesg /bin/findmnt /bin/logger /bin/lsblk /bin/more /bin/mount /bin/umount /sbin/adjtimex /sbin/agetty /sbin/blkid /sbin/blockdev /sbin/cfdisk /sbin/chcpu /sbin/ctrlaltdel /sbin/elvtune /sbin/fdisk /sbin/findfs /sbin/fsck /sbin/fsck.cramfs /sbin/fsck.minix /sbin/fsfreeze /sbin/fstrim /sbin/hwclock /sbin/losetup /sbin/mkfs /sbin/mkfs.bfs /sbin/mkfs.cramfs /sbin/mkfs.minix /sbin/mkswap /sbin/nologin /sbin/pivot_root /sbin/raw /sbin/sfdisk /sbin/swaplabel /sbin/swapoff /sbin/swapon /sbin/switch_root /sbin/wipefs /usr/bin/cal /usr/bin/chrp-addnote /usr/bin/chrt /usr/bin/col /usr/bin/colcrt /usr/bin/colrm /usr/bin/column /usr/bin/cytune /usr/bin/ddate /usr/bin/fallocate /usr/bin/flock /usr/bin/getopt /usr/bin/hexdump /usr/bin/i386 /usr/bin/ionice /usr/bin/ipcmk /usr/bin/ipcrm /usr/bin/ipcs /usr/bin/isosize /usr/bin/line /usr/bin/linux32 /usr/bin/linux64 /usr/bin/look /usr/bin/lscpu /usr/bin/mcookie /usr/bin/mesg /usr/bin/mkzimage_cmdline /usr/bin/namei /usr/bin/rename /usr/bin/renice /usr/bin/rev /usr/bin/script /usr/bin/scriptreplay /usr/bin/setarch /usr/bin/setsid /usr/bin/setterm /usr/bin/tailf /usr/bin/taskset /usr/bin/time /usr/bin/ul /usr/bin/uname26 /usr/bin/unshare /usr/bin/uuidgen /usr/bin/wall /usr/bin/whereis /usr/bin/which /usr/bin/write /usr/bin/x86_64 /usr/sbin/addpart /usr/sbin/delpart /usr/sbin/fdformat /usr/sbin/flushb /usr/sbin/freeramdisk /usr/sbin/klogconsole /usr/sbin/ldattach /usr/sbin/partx /usr/sbin/rcraw /usr/sbin/readprofile /usr/sbin/rtcwake /usr/sbin/setctsid /usr/sbin/tunelp
내 util-linux
는 버전 2.19입니다. 릴리스 노트는 2007 년 8 월 28 일자 v2.13으로 쉽게 찾을 수 있습니다. 이것의 요점이나 목표가 무엇인지 확실하지 않았기 때문에 331 번 찬성표를 던지는 긴 일에서 확실히 답변을받지 못했습니다.
댓글
- 질문은 그것이 가리키는 유닉스에 대해 언급하지 않습니다. Linux는 몇 가지 중 하나 일뿐입니다.
-
which -v
에서 알 수 있듯이 ‘ s GNU는 하나는 다른 답변에서 언급되었으며 Linux에만 국한되지 않음) AFAIK가which
유틸리티를 포함하지 않은 util-linux가 아닙니다. util-linux 2.19는 2011 년, GNU 2.19는 2008 년입니다.
which
사용에 대한 대부분의 주장은 대화 형 쉘 컨텍스트를 가정하고 있다고 생각합니다.이 질문은 / portability로 태그가 지정되어 있습니다. 이 컨텍스트에서 질문은 ”which
대신$PATH
“. 대부분의 답변 및 반대 이유which
는 대부분의 실제 휴대용 셸 스크립트에서 학문적 관심사 인 별칭, 내장 및 함수를 다룹니다. 로컬에서 정의 된 별칭은 ‘ 셸 스크립트를 실행할 때 상속되지 않습니다 (.
로 소싱하지 않는 한).csh
(그리고which
는 여전히 대부분의 광고에서csh
스크립트입니다. Unices)는 대화 형이 아닐 때~/.cshrc
를 읽습니다. 따라서 ‘ ‘ csh 스크립트가 일반적으로#! /bin/csh -f
로 시작하는 것을 알 수 있습니다.which
는 별칭을 제공하는 것이 목표 이기 때문이 아닙니다. ‘는 (대화 형)csh
의 사용자. POSIX 쉘 사용자에게는command -v
가 있습니다.(t)csh
이 아니면 항상 대답은 입니다. div> (또는 ‘ 정확한 결과를 제공하지 않아도 ‘ 걱정하지 않음)type
또는command -v
. 이유 에 대한 답변을 참조하세요.stat $(which ls)
는 여러 가지 이유로 잘못되었습니다 (, 따옴표 누락),which
의 사용뿐만 아니라). ‘stat -- "$(command -v ls)"
를 사용합니다. 이는ls
가 실제로 파일 시스템에서 발견되는 명령이라고 가정합니다 (셸의 내장 또는 별칭 기능이 아님).which
는 잘못된 경로 (ls
를 입력 한 경우 셸이 실행되는 경로가 아님)를 제공하거나 정의 된 별칭을 제공 할 수 있습니다. 일부 다른 셸의 구성에서 …which
구현이 사용자에게 제공하지 않는 여러 조건이 있습니다.ls
는$PATH
를 조회하여 찾을 수 있습니다 (ls
에 관계없이 쉘에서 호출 할 수 있습니다).sh -c 'command -v ls'
또는zsh -c 'rpm -q --whatprovides =ls'
가 정답을 제공 할 가능성이 더 높습니다. 여기서 요점은which
가csh
의 깨진 유산이라는 것입니다.