Bash 내장으로`exec` 실행 ( 예 :) clock ls -R. 내 셸

쉘 함수를 정의했습니다 (호출하자 clock) . 이 time함수 와 유사한 다른 명령에 대한 래퍼로 사용하고 싶습니다 ( 예 🙂 clock ls -R.

내 셸 함수는 몇 가지 작업을 수행 한 다음로 끝납니다 exec "$@".

이 기능을 쉘 내장에서도 사용할 수 있기를 원합니다. 예를 들어 실행 파일이 아닌 내장 clock time ls -R결과를 출력해야합니다 . 그러나 항상 대신 명령을 실행합니다.time/usr/bin/timeexec

bash 내장 함수를 인수로 허용하는 래퍼로 Bash 함수를 작동 시키려면 어떻게해야합니까?

편집 : 방금 time배쉬 내장이 아니라 파이프 라인과 관련된 특별한 예약어라는 것을 배웠습니다 . 와 함께 작동하지 않더라도 내장 솔루션에 관심이 time있지만 더 일반적인 솔루션이 더 좋습니다.



답변

bash 함수를 정의했습니다. 따라서 해당 기능을 호출 할 때 이미 bash 쉘에 있습니다. 따라서 해당 기능은 다음과 같이 간단하게 나타납니다.

clock(){
  echo "do something"
  $@
}

이 함수는 bash 내장, 특수 예약어, 명령 및 기타 정의 된 함수를 사용하여 호출 할 수 있습니다.

별명 :

$ clock type ls
do something
ls is aliased to `ls --color=auto'

bash 내장 :

$ clock type type
do something
type is a shell builtin

다른 기능 :

$ clock clock
do something
do something

실행 파일 :

$ clock date
do something
Tue Apr 21 14:11:59 CEST 2015


답변

쉘 내장 또는 쉘 키워드를 시작하는 유일한 방법은 exec가 “주어진 명령으로 쉘을 대체하기”때문에 새 쉘을 시작하는 것입니다. 마지막 줄을 다음과 같이 바꿔야합니다.

IFS=' '; exec bash -c "$*"

이것은 내 장어와 예약어 모두에서 작동합니다. 원칙은 같습니다.


답변

래퍼가 주어진 명령 전에 코드를 삽입해야하는 경우, 매우 초기 단계에서 확장 될 때 별명이 작동합니다.

alias clock="do this; do that;"

별명은 거의 별명으로 된 단어 대신 문자 그대로 삽입되므로 후행 ;이 중요 clock time foo합니다 do this; do that; time foo.

이를 악용 하여 인용을 우회하는 마술 별칭 을 만들 수 있습니다 .


명령 뒤에 코드를 삽입 하려면 “DEBUG”훅을 사용할 수 있습니다.

shopt -s extdebug
trap "<code>" DEBUG

구체적으로 특별히:

shopt -s extdebug
trap 'if [[ $BASH_COMMAND == "clock "* ]]; then
          eval "${BASH_COMMAND#clock }"; echo "Whee!"; false
      fi' DEBUG

후크는 여전히 명령 전에 실행 되지만 반환 false되면 bash가 실행을 취소하도록 지시합니다 (훅이 이미 eval을 통해 실행 되었기 때문에).

다른 예로서, 이것을 사용하여 다음과 같이 별칭 command please을 지정할 수 있습니다 sudo command.

trap 'case $BASH_COMMAND in *\ please) eval sudo ${BASH_COMMAND% *}; false; esac' DEBUG


답변

지금까지 내가 취할 수있는 유일한 해결책은 첫 번째 인수가 명령, 내장 또는 키워드인지 여부를 구별하기 위해 사례 분석을 수행하고 마지막 경우에는 실패하는 것입니다.

#!/bin/bash

case $(type -t "$1") in
  file)
    # do stuff
    exec "$@"
    ;;
  builtin)
    # do stuff
    builtin "$@"
    ;;
  keyword)
    >&2 echo "error: cannot handle keywords: $1"
    exit 1
    ;;
  *)
    >&2 echo "error: unknown type: $1"
    exit 1
    ;;
esac

time그러나을 처리하지 않으므로 더 나은 (그리고 더 간결한) 솔루션이있을 수 있습니다.


답변