“ 어떤 ”를 사용하지 않으시겠습니까? 그러면 무엇을 사용해야합니까?

실행 파일의 경로를 찾거나 Unix 셸에 명령 이름을 입력하면 어떤 일이 발생하는지 확인할 때 “다양한 유틸리티 ( which, type, command, whence, where, whereis, whatis, hash 등).

which를 피해야한다는 말을 자주 듣습니다. 그 이유는 무엇입니까? 대신 무엇을 사용해야합니까?

댓글

  • which 사용에 대한 대부분의 주장은 대화 형 쉘 컨텍스트를 가정하고 있다고 생각합니다.이 질문은 / portability로 태그가 지정되어 있습니다. 이 컨텍스트에서 질문은 ” which 대신 $PATH “. 대부분의 답변 및 반대 이유 which는 대부분의 실제 휴대용 셸 스크립트에서 학문적 관심사 인 별칭, 내장 및 함수를 다룹니다. 로컬에서 정의 된 별칭은 ‘ 셸 스크립트를 실행할 때 상속되지 않습니다 (.로 소싱하지 않는 한).
  • @MattBianco, 예, csh (그리고 which는 여전히 대부분의 광고에서 csh 스크립트입니다. Unices)는 대화 형이 아닐 때 ~/.cshrc를 읽습니다. 따라서 ‘ ‘ csh 스크립트가 일반적으로 #! /bin/csh -f로 시작하는 것을 알 수 있습니다. which는 별칭을 제공하는 것이 목표 이기 때문이 아닙니다. ‘는 (대화 형) csh의 사용자. POSIX 쉘 사용자에게는 command -v가 있습니다.
  • @rudimeier, 그러면 쉘이 (t)csh이 아니면 항상 대답은 입니다. div> (또는 ‘ 정확한 결과를 제공하지 않아도 ‘ 걱정하지 않음) type 또는 command -v . 이유 에 대한 답변을 참조하세요.
  • @rudimeier, (stat $(which ls)는 여러 가지 이유로 잘못되었습니다 (, 따옴표 누락), which의 사용뿐만 아니라). ‘ stat -- "$(command -v ls)"를 사용합니다. 이는 ls가 실제로 파일 시스템에서 발견되는 명령이라고 가정합니다 (셸의 내장 또는 별칭 기능이 아님). which는 잘못된 경로 (ls를 입력 한 경우 셸이 실행되는 경로가 아님)를 제공하거나 정의 된 별칭을 제공 할 수 있습니다. 일부 다른 셸의 구성에서 …
  • @rudimeier, 다시 말하지만, 많은 which 구현이 사용자에게 제공하지 않는 여러 조건이 있습니다. ls$PATH를 조회하여 찾을 수 있습니다 (ls에 관계없이 쉘에서 호출 할 수 있습니다). sh -c 'command -v ls' 또는 zsh -c 'rpm -q --whatprovides =ls'가 정답을 제공 할 가능성이 더 높습니다. 여기서 요점은 whichcsh의 깨진 유산이라는 것입니다.

답변

여기에 대해 알고 싶지 않을 것이라고 생각한 적이없는 모든 것이 있습니다.

요약

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 년경에 별칭을 도입했지만 csh2BSD 출시 되었습니다. / 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 (및 akangaes)와 같은 파생 상품에도 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 -pwhence -p) 및 -a는 일치하는 명령을 모두 보고합니다. tcshwhich를 내장하고 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 (tcshzsh의 기본 제공 항목 제외) ) 우리는 몇 가지 구현을 찾습니다. 예를 들어 최신 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는 어떤 표준에도 지정되지 않음). .

일부 버전까지 typecommand -v는 Linux Standard Base 사양에서 선택 사항으로 예를 들어 일부 이전 버전의 posh (둘 다 포함 된 pdksh 기반)에는 둘 중 하나가 없었습니다. command -v도 일부 Bourne 셸 구현 (예 : Solaris)에 추가되었습니다.

오늘의 상태

요즘의 상태는 typecommand -v가 모두 어디에나 있다는 것입니다. Bourne과 같은 셸 (@jarno에서 언급했듯이 POSIX 모드가 아닌 경우 bash의 경고 / 버그 또는 주석 아래 Almquist 셸의 일부 하위 항목). tcshwhich를 사용하려는 유일한 셸입니다 (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 foofoo를 반환합니다. 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

를 사용할 수있는 곳 cshtcsh에서는 선택의 여지가별로 없습니다. 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는 실행 가능한 것을 실행합니다 (잘못된 하나도 해시 됨). FreeBSD sh (또한 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 명령을 래핑하는 시스템 전체에 정의 된 별칭이 있습니다.

가짜 출력은 whichbash “의 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 스크립트입니다. 제 경우에는 shdash이지만 bash.

설정되지 않은 PATHPATH 조회를 비활성화하는 것이 아니라 시스템의 기본 경로 는 안타깝게도 Debian에서는 아무도 동의하지 않습니다 (dashbash에는 /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가 있습니다 (예, 현재 디렉토리를 먼저 확인합니다!). .

whichdash “의 기본 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, 모든 시스템 :

Chris가 답변에서 언급 한 사람 :

$ 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 

whichtypeb/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 lsls 여부에 관계없이 /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 년입니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다