명령 하위 명령 구조 외에도 Bash는 command.subcommand 구조도 지원합니까? 그렇다면 어떻게 bash 스크립트에 통합할 수 있습니까?

명령 하위 명령 구조 외에도 Bash는 command.subcommand 구조도 지원합니까? 그렇다면 어떻게 bash 스크립트에 통합할 수 있습니까?

내 로컬 컴퓨터에 microk8s(Micro Kubernetes)를 설치한 후 내가 만난 명령 중 하나 microk8s.enable dnsmicrok8s enable dns. git status유효한 명령이지만 git.status그렇지 않습니다. Linux 시스템은 이러한 유형의 명령 구조를 어떻게 지원합니까? 이 동작을 Bash 스크립트에 어떻게 통합할 수 있나요?

답변1

때때로 프로그램(및 스크립트)이 프로그램을 호출하는 데 사용된 파일 이름을 확인하고 해당 파일을 기반으로 동작을 결정하는 것을 볼 수 있습니다.

예를 들어 다음 파일과 심볼릭 링크를 고려해보세요.

$ ls -l
-rwxr-xr-x  ... foo
lrwxr-xr-x  ... foo.bar -> foo

그리고 스크립트의 내용은 다음과 같습니다 foo.

#!/bin/bash

readonly command="$(basename "${0}")"
subcommand="$(echo "${command}" | cut -s -d. -f2)"

if [[ "${subcommand}" == "" ]]; then
    subcommand="${1}"
fi

if [[ "${subcommand}" == "" ]]; then
    echo "Error: subcommand not specified" 1>&2
    exit 1
fi

echo "Running ${subcommand}"

스크립트는 명령 이름을 구문 분석하여 하위 명령을 찾습니다(질문의 점 표기법을 기반으로 함). 이렇게 하면 실행 ./foo.bar과 동일한 동작을 실행할 수 있습니다 ./foo bar.

$ ./foo.bar
Running bar

$ ./foo bar
Running bar

microk8s.enable분명히 말하자면, 나는 이것이 행해지고 있는 일 이 무엇인지 모릅니다 . 이러한 파일을 실행 ls -li $(which microk8s.enable) $(which microk8s)하고 비교할 수 있습니다. 하나는 다른 하나에 대한 링크입니까? 그렇지 않다면 inode 번호가 동일합니까?

답변2

이는 사용된 "하위 명령"에 따라 여러 작업을 수행할 수 있는 도구를 제공하는 매우 일반적인 방법이 되었습니다. 내가 아는 한, 어떤 식으로든 표준화되지 않았으며 기본 명령 이름과 하위 명령을 함께 작성할 때 점을 구분 기호로 사용하는 것은 이러한 도구에서 확실히 보편적이지 않습니다.

일부 도구는 하위 명령을 통해서만 호출할 수 있습니다 git( 예: git단독으로 호출할 경우 자체적으로 도움말 텍스트 제공).수동유사한 하위 명령의 경우 man command-subcommand(하위 명령의 경우 git)

당신은 분명히 command-subcommand호출할 수 있는 도구를 찾았습니다(그러나 점이 있음).또는처럼 command subcommand. 이 경우 기본 명령과 결합된 각 명령이 동일한 파일에 대한 기호 링크 또는 하드 링크임을 알 수 있습니다.

프로그램(스크립트이든 컴파일된 바이너리이든)은 이름과 인수를 호출하여 쉽게 검사하고 그에 따라 작동을 조정할 수 있습니다.

process다음은 에서처럼 하위 명령을 첫 번째 인수로 사용하거나 process action에서처럼 하위 명령으로 호출할 수 있는 가상 명령의 예입니다 process-action.

이 스크립트에 의해 구현된 하위 명령은 compile, debug, , 입니다 mogrify.

#!/bin/sh

basecmd=process         # base command name
cmd=${0##*/}            # get command name ( basename "$0" )
subcmd=                 # no sub command yet

# Now pick out the sub command from the command name,
# or from the first argument.  Then fail if unsuccessful.

case $cmd in
        "$basecmd"-*)   # has sub command in command name
                subcmd=${cmd#$basecmd-}
esac

if [ -z "$subcmd" ] && [ "$#" -ge 1 ]; then
        # called as "process action"
        # rather than as "process-action"
        subcmd=$1
        shift   # remove sub command from argument list
fi

if [ -z "$subcmd" ]; then
        echo 'No action' >&2
        exit 1
fi

# Act on the sub command.
# Each action would probably be implemented as a function,
# possibly called as
#     somefunction "$@"
# ... passing the remaining command line argument to it.

case $subcmd in
        compile)        # do "compile" action
                echo 'compile'
                ;;
        debug)          # do "debug" action
                echo 'debug'
                ;;
        mogrify)        # do "mogrify action"
                echo 'mogrify'
                ;;
        *)
                printf 'Invalid action "%s"\n' "$subcmd" >&2
                exit 1
esac

POSIX를 위해 이 글을 쓴 이유는 sh작업하는 데 난해한 것이 필요하지 않기 때문입니다. bashAC 프로그램은 다른 컴파일 또는 해석 언어로 작성된 프로그램과 유사한 방식으로 작업을 수행합니다. 여기에는 Linux도 필요하지 않습니다. OpenBSD에서 작성하고 테스트하고 있으며 모든 POSIX 시스템에서 작동합니다.

이 기본 process스크립트와 함께 각 하위 명령에 하나씩 일련의 하드 또는 기호 링크가 있습니다. 여기서는 하드 링크를 생성하도록 선택합니다.

$ ls -li
total 8
244420 -rwxr-xr-x  4 kk  wheel  538 May  9 21:55 process
244420 -rwxr-xr-x  4 kk  wheel  538 May  9 21:55 process-compile
244420 -rwxr-xr-x  4 kk  wheel  538 May  9 21:55 process-debug
244420 -rwxr-xr-x  4 kk  wheel  538 May  9 21:55 process-mogrify

이러한 이름은 각각 동일한 스크립트의 또 다른 이름일 뿐입니다.

시험 실행:

$ ./process mogrify
mogrify
$ ./process-mogrify
mogrify
$ ./process
No action
$ ./process-compile
compile
$ ./process compile
compile
$ ./process compilee
Invalid action "compilee"

관련 정보