매개변수 내용을 실행하지 않고 명령에 매개변수를 전달하는 방법은 무엇입니까?

매개변수 내용을 실행하지 않고 명령에 매개변수를 전달하는 방법은 무엇입니까?

좋은 시간.

약간의 문제가 있습니다. bash 스크립트에 이 기능이 있습니다

function denyCheck(){
    file=$(readlink -f $(which $(printf "%s\n" "$1")))
    if [[ -x $file ]];then
           return false
    else
           return true
    fi
}
denyCheck "firefox"

이 함수는 그녀에게 명령이 무엇인지 문자열을 전달합니다. 이는 명령이 있는 원래 경로(예: /usr/lib/firefox/firefox.sh)를 확인하고 파일이 실행 가능하면 true를 반환하고 그렇지 않으면 false를 반환합니다.

하지만 문제는... 매개변수(예: "firefox")가 이를 명령으로 실행하고 브라우저 Firefox를 연다는 것입니다.

매개변수가 실행되지 않도록 하려면 어떻게 해야 합니까?

매우 감사합니다.

답변1

그 이상이어야 합니다:

cmd_canonical_path() {
  local cmd_path
  cmd_path=$(command -v -- "$1") &&
    cmd_path=$(readlink -e -- "$cmd_path") &&
    [ -x "$cmd_path" ] &&
    REPLY=$cmd_path
} 2> /dev/null

그런 다음 예를 들어 다음을 사용하십시오.

if cmd_canonical_path firefox; then
  printf '%s\n' "firefox found in $REPLY executable"
else
  printf >&2 '%s\n' "no executable file found for firefox"
fi

셸에서 모든 명령에는 성공(0) 또는 실패(다양한 유형의 실패를 구별하는 데 도움이 되는 값을 갖는 다른 숫자)를 나타내는 종료 상태가 있습니다.

예를 들어, 명령을 실행하는 프로세스에 파일(또는 디렉터리)에 대한 실행 권한이 있는 경우 [명령은 -x인수로 전달될 때 true를 반환합니다./path/to/some/file]/path/to/some/file

함수에는 반환 전 마지막 명령 실행의 종료 상태(또는 return호출 시 전달된 숫자)인 종료 상태도 있을 수 있습니다.

if명령의 성공 또는 실패 상태는 // 문이나 해당 부울 연산자 sum 과 같은 쉘 구성으로 until확인됩니다 .while||&&주문하다원하는 경우 셸의 부울 값입니다.

cmd1 && cmd2 && cmd3성공 / true를 반환합니다. 모두 예 이고 cmd1성공입니다 . 실패해도 실행 되지 않습니다 .cmd2cmd3cmd2cmd1cmd3

cmd_canonical_path따라서 위의 경우 성공합니다 command -v -- "$1"(명령을 찾고 해당 경로를 인쇄하기 위한 표준 내장1 명령; which일부 유사한 명령이지만 csh 사용자에게만 해당).그리고그런 다음 readlink -e(정규화된 경로처럼 작동 하지만, 최선의 노력을 다하면서 readlink -f할 수 없으면 실패를 반환합니다 ) 성공readlink -f그리고그런 다음 현재 프로세스에는 파일에 대한 실행 권한이 있습니다.그리고그런 다음에만 경로가 REPLY4번째 변수에 성공적으로 할당됩니다(일반 할당은 항상 성공합니다).

cmd && cmd && cmd그렇지 않은 경우 함수는 실패(실패한 체인의 첫 번째 명령의 종료 상태)를 반환합니다.

$REPLY또한 명령에 대한 정식 경로를 결정할 수 없거나 명령을 실행할 수 없는 경우 명령이 수정되지 않고 보존된다는 점도 참고하세요 .

귀하의 접근 방식에는 몇 가지 다른 문제가 있습니다.

  • 이것은 $(printf '%s\n' "$1")별로 의미가 없습니다. sh/bash에서는 $1(적어도 기본값)과 동일하며 $IFS인용되지 않았기 때문에 똑같이 잘못되었습니다. 첫 번째 위치 인수의 내용을 명령에 전달하려는 경우 구문은 입니다 cmd "$1".
  • 옵션이 아닌 인수로 처리되도록 명령에 전달된 임의의 데이터를 원하는 경우 --옵션의 끝을 표시하는 인수 뒤에 이를 전달해야 합니다: which -- "$1", readlink -f -- "$(...)".
  • returntrue/ 대신 (선택적) 숫자를 인수(함수의 종료 코드)로 허용합니다 false(파일이 실행 가능하면 함수가 true를 반환한다고 말했기 때문에 이를 반대로 한 것 같습니다). 숫자가 전달되지 않으면 함수의 종료 상태는 함수 내에서 실행된 마지막 명령의 종료 상태가 됩니다. 그래서 if cmd; then return 0; else return 1; fi그냥 쓰는 것이 가장 좋습니다 cmd; return. 여기서는 ( 귀하의 경우) 함수의 마지막 명령이기 return때문에 필요하지 않습니다 .cmd[[ -x $file ]]
  • 먼저 성공 여부를 확인하지 않고 which(을 잊어버리고 --인용했기 때문에 부정확하게 $(...)) 의 출력을 맹목적으로 전달했습니다 .readlink

마지막으로 를 대신 사용하면 zsh다음 bash과 같이 할 수 있습니다.

firefox_path==firefox
firefox_canonical_path=$firefox_path:P

firefox명령의 경로를 가져옵니다 . =firefox명령의 경로로 확장하여 firefox명령을 찾을 수 없으면 오류와 함께 셸을 중단합니다. 오류를 차단할 수 있습니다.always막힌필요한 경우. 이 :P수정자는 realpath()GNU의 작업과 유사하게 적용되는 인수에 대해 동일한 작업을 수행합니다 readlink -f. zsh=cmd연산자는 실행 경로로만 확장되므로 실행 권한을 확인할 필요가 없습니다 .


¹ 셸에 내장된 구성 요소이므로 셸 설명서에서 해당 설명서를 찾을 수 있습니다. 에 대해서는 예를 bash참조하세요 info bash command.

² command -v cmd출력 cmdcmd함수 또는 셸 내장 함수이므로 문제가 될 수 있습니다.

³ 표준 절대 경로는 로 시작하고 /, 심볼릭 링크 구성 요소가 없으며(모두 대상으로 확인됨), / 구성 요소가 없으며 , 두 개 이상의 s 시퀀스가 .​​없습니다 .../

4는 $REPLY 함수나 쉘 내장 함수의 반환 값에 대한 기본 변수로 자주 사용됩니다(단지 관례일 뿐임). 또는 함수에서 다음을 수행할 수 있습니다.산출결과적으로 호출자는 를 실행합니다 firefox_path=$(cmd_canonical_path firefox).

답변2

이것:

function denyCheck(){

func()표준 함수 선언과 ksh 가 혼합되어 있습니다 function func. Bash는 이 조합을 지원하고 다른 쉘은 그렇지 않을 수도 있지만 그럴 이유가 없습니다. 그냥 써 denyCheck().

여기,

file=$(readlink -f $(which $(printf "%s\n" "$1")))

이는 $(printf ...)불필요하며 인용되지 않았기 때문에 실제로는 비생산적입니다. 이 명령 대체의 결과는 다음의 영향을 받습니다.분사, 인용된 내용은 "$1"그렇지 않으므로 대신 사용할 수 있습니다.

which몇 가지 문제가 있는 것으로 간주되는 표준 POSIX 대안은 다음을 command -v참조하세요." which "를 사용하지 않는 이유는 무엇입니까? 그러면 무엇을 사용해야 합니까?

둘 사이의 가장 큰 차이점은 command내장 셸이고 예를 들어 별칭에 대해 알고 있는 반면(대화형 셸에서 실행하는 경우) 그렇지 which않다는 것입니다(csh를 제외하고 사용하지 않음). 이는 좋은 것일 수도 있고 아닐 수도 있습니다. 예를 들어 사용할 수 있는 경로가 아닌 를 command -v ls반환할 수 있습니다 .alias ls='ls -vF --color=auto'

--어떤 경우든 단어 분리 문제를 방지하고 태그 옵션의 끝 부분을 추가하려면 명령 대체를 인용해야 합니다 . 이는 공백을 포함하거나 로 끝나는 드문 경로를 방지하기 위한 것입니다 -.

file=$(readlink -f -- "$(command -v -- "$1")")  # or
file=$(readlink -f -- "$(which -- "$1")") 

그 다음에,

return false

단지 버그입니다. return명령에 숫자가 필요합니다. 그러나 false오류의 반환 상태를 가져오기 위해 명명된 명령을 실행할 수 있습니다 . 따라서 또는 return 1just 중 하나를 사용하십시오 false. (테스트 결과를 반전시키는 것이므로 ! [[ -x "$file" ]]전체 if명령문 대신 just를 사용할 수도 있습니다. 이를 작성하면 다음 독자에게 더 명확해질 수 있습니다.)

그래서:

denycheck() {
    file=$(readlink -f -- "$(command -v -- "$1")")
    if [[ -x "$file" ]]; then
        return 1  # command found and executable, falsy result
    else
        return 0  # not executable, truthy result
    fi
}

관련 정보