시스템 기본 $PATH와 함께 which(1)을 사용하는 방법은 무엇입니까?

시스템 기본 $PATH와 함께 which(1)을 사용하는 방법은 무엇입니까?

which사용자 쉘 구성 파일의 수정 사항을 무시하고 시스템의 기본 경로를 사용하고 싶습니다 .

동기 부여

내 시스템의 Ruby 바이너리를 찾기 위한 스크립트를 작성하려고 합니다. 많은 Ruby 개발자는 Ruby 버전 관리자를 사용하고 이를 자신 ~/.rvm/bin$PATH.

현재 솔루션

이것이 내가 지금까지 시도한 것입니다:

$ env -i sh -c "which ruby"

이는 출력을 제공하지 않고 1로 종료됩니다. 경로에 다음이 포함되어 /usr/bin있고 내 시스템에 Ruby 바이너리가 함께 제공되므로 작동할 것으로 예상합니다 /usr/bin/ruby.

$ env -i sh -c "echo \$PATH"
/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.
$ which -a ruby
# ...
/usr/bin/ruby

몇 가지 추가 세부정보:

  • env -s bash -c "which ruby"아무것도 발견되지 않았습니다.
  • env -i zsh -c "which ruby"실제로 찾았 /usr/bin/ruby지만 믿을 수는 없습니다 zsh.
  • 전체 경로를 사용하면 which(셸 내장이 아닌 바이너리를 사용하고 있는지 확인하기 위해) 아무런 차이가 없습니다.

내 환경

저는 OS X의 Bash에서 이 글을 쓰고 있지만, 다른 쉘과 운영 체제로 이식할 수 있기를 바랍니다.

답변1

command -pv"PATH의 기본값"을 사용하십시오.

$ which ruby
/home/mikel/.rvm/rubies/ruby-1.9.3-p484/bin/ruby

$ command -pv ruby
/usr/bin/ruby

불행히도 이것은 에서는 작동하지 않으므로 zshStephane의 의견을 바탕으로 다음을 사용할 수 있습니다 getconf PATH.

$ PATH=$(getconf PATH) which ruby

또는 command -v제안된 대로 which사용하십시오 ." which "를 사용하지 않는 이유는 무엇입니까? 그러면 무엇을 사용해야 합니까?

$ PATH=$(getconf PATH) command -v ruby

이러한 방법의 단점은 시스템 관리자가 /usr/local/bin예 를 들어 시스템 /opt/local/bin전체 버전을 설치한다는 것입니다.PATH/etc/profile/etc/environment

상황에 따라 Ruby 관련 접근 방식을 시도해 보는 것이 좋습니다. 다음은 효과가 있을 수 있는 몇 가지 아이디어입니다.

  1. 사용자의 홈 디렉터리(및 상대 경로)에서 버전을 필터링합니다.

    (
        IFS=:
        set -f
        for dir in $PATH; do
            case $dir/ in
                "$HOME/"*) ;;
                /*/)
                    if [ -f "$dir/ruby" ] && [ -x "$dir/ruby" ]; then
                        printf '%s\n' "$dir/ruby"
                        break
                    fi;;
            esac
        done
    )
    
  2. rvm 디렉터리의 버전을 필터링합니다.

    (
        IFS=:
        set -f
        for dir in $PATH; do
            case $dir/ in
                "$rvmpath/"*) ;;
                /*/)
                    if [ -f "$dir/ruby" ] && [ -x "$dir/ruby" ]; then
                        printf '%s\n' "$dir/ruby"
                        break
                    fi;;
            esac
        done
    )
    
  3. 쓰기 가능한 루비 필터링(최후의 수단, 루트로 실행되지 않는다고 가정)

    (
        IFS=:
        set -f
        for dir in $PATH; do
            case $dir/ in
                /*/)
                    ruby=$dir/ruby
                    if [ -f "$ruby" ] && [ -x "$ruby" ] && [ ! -w "$ruby" ]; then
                        printf '%s\n' "$ruby"
                        break
                    fi;;
            esac
        done
    )
    
  4. 물어 rvm보세요 chruby. 잠시만요.

    (
        rvm system
        chruby system
        command -v ruby
    )
    

마지막 방법은 rvm기본 Ruby를 선택하지만 나중에 사용자가 선호하는 Ruby를 복원할 수 있도록 하위 쉘에서 이 작업을 수행합니다. ( chruby부분적으로 테스트되지 않았습니다.)

답변2

$PATH서브셸에서 명시적으로 값을 설정하면 문제가 해결됩니다.

env -i sh -c "PATH=\$PATH which ruby"

$in은 이스케이프 처리됩니다. 이는 $PATH명령을 실행하기 전에 $PATH하위 쉘 명령이 상위 쉘의 값으로 대체되지 않음 을 의미합니다(작은따옴표를 사용하여 수행할 수도 있음).$PATH

이 경우에 이것이 왜 필요한지 알고 싶습니다.

답변3

일반적으로 이 명령을 사용하고 싶지 않습니다 which. Bash에서는 typeor 명령을 사용해야 합니다 command. 이유를 알아보려면 다음 Q&A를 참조하세요." which "를 사용하지 않는 이유는 무엇입니까? 그러면 무엇을 사용해야 합니까?.

$ type -a ls
ls is aliased to `ls --color=auto'
ls is /bin/ls

아니면 이거:

$ type -a vim
vim is /usr/bin/vim

아니면 이거:

$ command -v ls
alias ls='ls --color=auto'

아니면 이거:

$ command -v vim
/usr/bin/vim

Bash 매뉴얼 페이지에서.

유형 발췌

type [-aftpP] name [name ...]
     With no options, indicate how each name would be interpreted if used as a
     command name.  If the -t option is used, type  prints a  string  which  is
     one  of  alias, keyword, function, builtin, or file if name is an alias,
     shell reserved word, function, builtin, or disk file, respectively.  If the
     name is not found, then nothing is  printed, and  an exit status of false
     is returned.  If the -p option is used, type either returns the name of the
     disk file that would be executed if name were specified as a command name,
     or nothing if ``type -t name'' would  not  return file.   The  -P  option
     forces a PATH search for each name, even if ``type -t name'' would not
     return file.  If a command is hashed, -p and -P print the hashed value, not
     necessarily the file that appears first in PATH.  If  the -a option is used,
     type prints all of the places that contain an executable named name.  This
     includes aliases and functions, if and only if the -p option is not also
     used.  The table of hashed commands  is  not  consulted  when using  -a.
     The -f option suppresses shell function lookup, as with the command
     builtin.  type returns true if all of the arguments are found, false if
     any are not found.

순서에 따른 발췌

   command [-pVv] command [arg ...]
         Run command with args suppressing the normal shell function lookup.
         Only builtin commands or commands found in the PATH are executed.  If
         the -p option is given, the search for command is performed using a
         default value for PATH that  is  guaranteed to find all of the standard
         utilities.  If either the -V or -v option is supplied, a description of
         command is printed.  The -v option causes a single word indicating the
         command or file name used to invoke command to  be displayed; the -V
         option produces a more verbose description.  If the -V or -v option is
         supplied, the exit status is 0 if command was found, and 1 if not.
         If neither option is supplied and an error  occurred  or command
         cannot be  found, the exit status is 127.  Otherwise, the exit status
         of the command builtin is the exit status of command.

답변4

env에 대한 인수로 PATH 설정을 "/usr/bin"으로 지정하거나 적절한 PATH를 설정하기만 하면 됩니다. env -i는 상속된 환경을 무시합니다. 다음 PATH 설정을 사용하면 /usr/bin/ruby를 찾을 수 있습니다.

env -i PATH="/usr/bin" sh -c "which ruby" 

관련 정보