Linux,Unix,BSD

[shell] 명령어 유무 확인하기(command, which)

채윤아빠 2022. 6. 9. 08:19
728x90
반응형

개요

특정 명령어가 존재하는지(설치되었는지) 확인할 때, "which"를 이용하거나, "command" 명령을 이용할 수 있습니다.


"which"와 "command" 명령간의 차이점을 살펴하고, 어떤 식으로 사용하면 될지 알아 보겠습니다.


which 명령

명령의 위치를 찾을 때 흔히 "which" 명령을 이용할 수 있습니다.

다음은 "which" 명령에 대한 man 설명서 입니다.

WHICH(1)                                     General Commands Manual                                     WHICH(1)

NAME
       which - locate a command

SYNOPSIS
       which [-a] filename ...

DESCRIPTION
       which  returns  the  pathnames of the files (or links) which would be executed in the current environment,
       had its arguments been given as commands in a strictly POSIX-conformant shell.  It does this by  searching
       the PATH for executable files matching the names of the arguments.  It does not canonicalize path names.

OPTIONS
       -a     print all matching pathnames of each argument

EXIT STATUS
       0      if all specified commands are found and executable

       1      if one or more specified commands is nonexistent or not executable

       2      if an invalid option is specified

Debian                                             29 Jun 2016                                           WHICH(1)

다음과 같은 형식으로 쉘 스크립트에서 "screen" 명령 유무에 따라 처리할 수 있습니다.

#!/bin/bash

if which screen &> /dev/null ; then
    screen -dmS 
else
    echo "screen not found!!"
    exit -1
fi

"which" 명령의 "type" 정보를 확인해 보면 다음과 같습니다.

pi@raspberrypi:~ $ type which
which is hashed (/usr/bin/which)

"which" 명령은 외부 명령으로 별도의 프로세스가 실행되는 형식입니다.


command 명령

다음은 "command" 명령을 이용하여, "screen" 명령이 있을 경우에는 screen을 새로 열어 명령을 실행하고 그렇지 않은 경우에는 직접 명령을 실행하는 예제입니다.

#!/bin/bash

if command -v screen &> /dev/null ; then
    screen -dmS 
else
    echo "screen not found!!"
    exit -1
fi

"command" 명령에 대한 도움말 입니다.

pi@raspberrypi:~ $ command --help
command: command [-pVv] command [arg ...]
    Execute a simple command or display information about commands.

    Runs COMMAND with ARGS suppressing  shell function lookup, or display
    information about the specified COMMANDs.  Can be used to invoke commands
    on disk when a function with the same name exists.

    Options:
      -p    use a default value for PATH that is guaranteed to find all of
            the standard utilities
      -v    print a description of COMMAND similar to the `type' builtin
      -V    print a more verbose description of each COMMAND

    Exit Status:
    Returns exit status of COMMAND, or failure if COMMAND is not found.

"command" 명령으로 특정 명령을 실행하거나, 그 정보를 확인할 수 있습니다.

"command" 명령에 대한 "type"을 확인해 보면 다음과 같습니다.

pi@raspberrypi:~ $ type command
command is a shell builtin

즉, "command" 명령은 "which" 명령과 다르게 쉘 내장 명령이라는 점입니다. 그래서 "which" 명령과 같이 별도의 프로세스를 생성하지 않고 빠르게 결과를 반환해 줍니다.

그리고 몇몇 OS에서는 "which" 명령의 결과를 실제와 다르게 출력하는 경우도 있기 때문에, "which" 명령을 이용하는 것보다는 "command" 명령을 이용하는 것이 더 유용합니다.

한 가지 주의해야할 점은 "alias" 내장 명령에 의하여 특정 명령에 대한 별명을 잡아준 경우는 command 명령의 반환값에 실행 경로가 아닌 "alias" 정보가 반환된다는 점입니다.

pi@raspberrypi:~ $ type screen
screen is hashed (/usr/bin/screen)
pi@raspberrypi:~ $ type ls
ls is aliased to `ls -CF --color=auto'

"ls" 명령을 "alias" 명령으로 별명을 만든 경우, 실제 "ls" 명령의 경로가 아닌 "alias" 정보가 출력됩니다.

"command"와 유사한 명령으로 "hash", "type" 등이 있습니다.

pi@raspberrypi:~ $ hash --help
hash: hash [-lr] [-p pathname] [-dt] [name ...]
    Remember or display program locations.

    Determine and remember the full pathname of each command NAME.  If
    no arguments are given, information about remembered commands is displayed.

    Options:
      -d        forget the remembered location of each NAME
      -l        display in a format that may be reused as input
      -p pathname       use PATHNAME as the full pathname of NAME
      -r        forget all remembered locations
      -t        print the remembered location of each NAME, preceding
                each location with the corresponding NAME if multiple
                NAMEs are given
    Arguments:
      NAME      Each NAME is searched for in $PATH and added to the list
                of remembered commands.

    Exit Status:
    Returns success unless NAME is not found or an invalid option is given.
pi@raspberrypi:~ $ type --help
type: type [-afptP] name [name ...]
    Display information about command type.

    For each NAME, indicate how it would be interpreted if used as a
    command name.

    Options:
      -a        display all locations containing an executable named NAME;
                includes aliases, builtins, and functions, if and only if
                the `-p' option is not also used
      -f        suppress shell function lookup
      -P        force a PATH search for each NAME, even if it is an alias,
                builtin, or function, and returns the name of the disk file
                that would be executed
      -p        returns either the name of the disk file that would be executed,
                or nothing if `type -t NAME' would not return `file'
      -t        output a single word which is one of `alias', `keyword',
                `function', `builtin', `file' or `', if NAME is an alias,
                shell reserved word, shell function, shell builtin, disk file,
                or not found, respectively

    Arguments:
      NAME      Command name to be interpreted.

    Exit Status:
    Returns success if all of the NAMEs are found; fails if any are not found.

결론

"which" 명령과 "command", "hash", "type" 명령의 가장 큰 차이점은 "which" 명령 자체는 작만면 어쨌든 외부 명령이고 별도의 프로세스로 실행되는 명령이라는 점입니다. 이에 반하여 "command", "hash", "type" 명령은 내장(builtin) 명령입니다.


네 명령에 약간씩 차이가 있지만, 가장 기본적인 내용은 $PATH 경로내에 주어면 명령이 있는지 확인할 수 있다는 점은 대동소이합니다. 그렇지만 "which" 명령은 외부 프로그램으로 별도 프로세스로 동작하기 때문에 악용되기 쉽고, 실제로도 몇몇 시스템에서는 원래의 출력과는 다르게 가공된 출력을 표시하기도 한다는 점에서 내장 명령을 이용하는 것을 추천 드립니다.


참고자료