Bash에서 숨겨진 프로그램을 어떻게 찾을 수 있나요?

Bash에서 숨겨진 프로그램을 어떻게 찾을 수 있나요?

내가 가지고 있다고 가정 해 봅시다 PATH="home/bob/bin:/usr/bin". 저는 /home/bob/bin/foo몇 가지 수정 작업을 /usr/bin/foo수행한 다음 . 실제로 실제 foo는 여러 곳에 있을 수 있으므로 PATH에서 찾고 싶습니다. 내 새 foo 스크립트도 내 경로에 있으므로 foo를 호출할 수 없으며 이로 인해 재귀 호출이 발생하게 됩니다.

Bash 스크립트에서 이 작업을 수행하는 쉬운 방법이 있습니까? (PATH 요소를 반복하고 수동으로 검색하는 것 외에?)

답변1

다음을 사용하면 언제든지 두 번째 경로를 얻을 수 있습니다 foo.

foo=$(type -Pa foo | tail -n+2 | head -n1)

(파일 경로에 개행 문자가 포함되어 있지 않은 경우)

이는 상대 경로일 수 있으며 실행 후에는 더 이상 유효하지 않습니다 cd.

그러면 다음과 같이 할 수 있습니다:

hash -p "$foo" foo

그래서저것 foo실행할 때 호출됩니다 foo.

답변2

enum보다 더 좋은 것은 없다고 생각합니다 PATH. 그렇게 어렵지는 않습니다.

#!/bin/bash
set -f; IFS=:
for d in $PATH; do
  if [[ -f $d/foo && -x $d/foo && ! $d/foo -ef /home/bob/bin/foo ]]; then
    exec "$d/foo" "$@"
    exit 126
  fi
done
echo "$0: foo (real) not found in PATH"
exit 127

PATH에 빈 항목이 없다고 가정합니다. 빈 PATH 항목은 해롭습니다. .명시적으로 작성하십시오(또는 전혀 포함하지 않는 것이 더 좋습니다).

다른 프로그램이 아닌 명령줄에서만 실행하는 경우 foo스크립트가 아닌 함수로 만드세요. 함수 내에서 command foo함수를 숨기려면 실행하세요.

답변3

foo가 중요한 경우 스크립트에서 구성해야 합니다. 스크립트에 명시적으로 연결할 수 있으므로 이것이 좋은 습관이라고 생각합니다. 나는 간접적이거나 암시적이거나 숨겨진 것을 좋아하지 않습니다. 스크립트를 배포하려면 매우 단순해야 합니다.

그렇지 않고 꼭 찾아야 한다면 찾는 방법은 다음과 같습니다.

whereisfoo="$(which foo)"

만약 그것이 충분하지 않다면, 당신이 하고 있는 일이 너무 복잡할 것 같습니다.

답변4

나는 이것이 Giles의 답변보다 약간 덜 혼란스러운 접근 방식이라고 생각합니다(비록 이것이 주관적인 판단임을 인정하지만).

#!/bin/sh
this_dir=$(dirname "$0") # 또는 this_dir=$HOME/bin으로 하드코딩할 수도 있습니다.
redacted_PATH=$(echo ":${PATH}:" | sed -e "s:\:$this_dir\::\::" -e "s/^://" -e 's/:$// ')
if obliged_prog=$(PATH=$redacted_PATH which foo)
그 다음에
            ⋮ # /usr/bin/foo를 실행하기 전에 해야 할 일
        "$(obscured_prog)"논쟁          # "$@"일 수도 있고 아닐 수도 있습니다.
            ⋮ # /usr/bin/foo를 실행한 후 해야 할 일
기타
        echo "$0: PATH에서 foo(실수)를 찾을 수 없습니다."
            ⋮ # 원하는 모든 코드.
필리핀 제도

이는 이 개인 복사본이 있는 디렉터리를 제외 redacted_PATH하고 구성됩니다 .  의 시작과 끝에 콜론을 추가 하면 각 구성 요소의 앞과 뒤에 콜론이 오게 됩니다. 심지어 첫 번째와 마지막 구성 요소도 마찬가지입니다. 검색 횟수 는$PATH$HOME/binfooecho ":${PATH}:"$PATHsed

: $this_dir :

("clear"를 위한 공간을 추가하고) 다음으로 대체합니다.

:

즉, $this_dir에서 제거됩니다 ":${PATH}:". 그런 다음 선행 및 후행 콜론을 제거합니다.

PATH그런 다음 일시적으로 로 설정 $redacted_PATH 하고 foouse 를 검색합니다 which. 성공하면 실행하는 데 사용한 실제(공개/공유/시스템) 복사본에 대한 전체 경로(예: /bin/foo또는 ) 를 얻게 됩니다 . 일시적으로만 변경하는 것이므로 사용자 환경에 접근할 수 있으므로 실행 하면 존재하는 경우 찾을 수 있습니다 ./usr/bin/foofooPATH/bin/foo$PATH/bin/foobrillig$HOME/bin/brillig

$HOME/bin여러 번 발생하면 문제가 발생할 수 있지만 $PATH고치는 것은 어렵지 않습니다.

관련 정보