find에서 함수를 호출할 때 변수 범위

find에서 함수를 호출할 때 변수 범위

Bash 스크립트에서 From을 정의합니다. find문제는 변수의 범위가 함수로 확장되지 않는다는 것입니다. 함수에서 변수에 어떻게 접근하나요? 예는 다음과 같습니다.

variable="Filename:"

myfunction() {
    echo $variable $1
}

export -f myfunction

find . -type f -exec bash -c 'myfunction "{}"' \;

그러면 "Filename:" 문자열 없이 파일 이름이 출력됩니다.

find발견된 모든 파일에 대해 호출되고 find여전히 변수를 정의하도록 함수를 호출하는 더 좋은 방법이 있습니까 ?

답변1

귀하의 질문에 대한 답변은 아니지만 괜찮습니다.아니요하다:

find . -type f -exec bash -c 'myfunction "{}"' \;

이식성이 없다는 사실 외에도 파일 이름이 bash쉘 코드로 해석되기 때문에 매우 위험합니다. 예를 들어, 이라는 파일이 있다면 어떤 일이 일어날지 생각해 보세요 $(rm -rf ~). 써 내려 가다:

find . -type f -exec bash -c 'myfunction "$1"' find+bash {} \;

bash또는 더 나은 방법은 다음과 같습니다( 파일당 하나씩 실행 하지 않으려면 ).

find . -type f -exec bash -c 'for file do
  myfunction "$file"; done' find+bash {} +

이제 주제 질문에 답해 보겠습니다.

다음을 수행할 수 있습니다.

{ find . -type f -exec printf '%s\0' {} + | while IFS= read -ru3 -d '' file; do
  myfunction "$file"; done 3<&0 <&4 4<&-; } 4<&0

이렇게 하면 myfunction현재 셸 내에서 호출할 수 있으므로 다른 셸을 bash내보내거나 실행할 필요가 없습니다 .myfunctionbash

GNU, busybox 및 일부 BSD와 같은 조건자를 find지원하는 경우 교체 할 수 있습니다.-print0find-exec printf '%s\0' {} +-print0

답변2

variable환경 변수로 선언할 수 있습니다 .

export variable="Filename:"

답변3

난 이걸 할거야

#!/bin/bash

myfunction() {
    local var="Filename: "
    local file=$1 
        echo "$var" "$file"
    }

export -f myfunction
    find . -type f -exec bash -c 'myfunction {}' \;

변수를 지역 변수로 선언하고 "{}"를 첫 번째 위치 인수로 함수에 전달합니다 $1.

답변4

변수에 할당하면 쉘 변수로 시작됩니다. 환경 변수를 하위 프로세스에 전달하려면 이를 내보내야 합니다.

variable="Filename:"
export variable

export: 과 같은 줄에 과제를 넣을 수 있습니다 export variable="Filename:".

이 변수는 시작 쉘에는 표시되지만 find함수에는 표시되지 않습니다. Bash에서는 함수를 내보낼 수도 있습니다. ksh, dash 및 기타 자주 사용되는 쉘에는 이러한 가능성이 존재하지 않습니다. sh더 빠르고 효율적이기 때문입니다.

export -f myfunction    # bash only

{}파일 이름이 영숫자라는 것을 알지 않는 한 ( 또는 )의 문자열 내에서 사용하지 마십시오 . 파일 이름에 특수 문자가 있으면 내부 쉘이 이를 구문 분석합니다. 대신, 쉘의 명령줄에 파일 이름을 전달하십시오.find -exec …xargs …

find . -type f -exec bash -c 'for x; do myfunction "$x"; done' _ {} +

Bash 이외의 쉘의 경우 내부 쉘에서 함수를 정의하거나 해당 코드를 직접 입력하십시오.

또는 bash에서는 find 대신 재귀 와일드카드를 사용할 수 있습니다. Bash는 디렉토리에 대한 심볼릭 링크를 통과합니다.

variable="Filename:"
myfunction () { … }
shopt -s globstar dotglob
for x in **/*; do
  if [[ -f $x ]]; then myfunction "$x"; fi
done

관련 정보