find
셸에서 정의한 함수를 실행 하는 방법이 있습니까? 예를 들면 다음과 같습니다.
dosomething () {
echo "doing something with $1"
}
find . -exec dosomething {} \;
그 결과는 다음과 같습니다.
find: dosomething: No such file or directory
얻을 수있는 방법이 있습니까 find
의를 -exec
볼 수는 dosomething
?
답변
쉘만이 쉘 함수를 실행하는 방법을 알고 있으므로 함수를 실행하려면 쉘을 실행해야합니다. 또한로 내보내기를 위해 함수를 표시해야합니다 export -f
. 그렇지 않으면 서브 쉘이이를 상속하지 않습니다.
export -f dosomething
find . -exec bash -c 'dosomething "$0"' {} \;
답변
find . | while read file; do dosomething "$file"; done
답변
위의 Jak의 대답은 훌륭하지만 쉽게 극복 할 수있는 몇 가지 함정이 있습니다.
find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done
줄 바꿈 대신 구분 기호로 null을 사용하므로 줄 바꿈이있는 파일 이름이 작동합니다. 또한 -r
파일 이름의 백 슬래시가 작동하지 않으면 백 슬래시 이스케이프를 비활성화 하는 플래그를 사용합니다. 또한 IFS
이름의 잠재적 인 후행 공백이 삭제되지 않도록 지 웁니다 .
답변
{}
아래와 같이 따옴표를 추가하십시오 .
export -f dosomething
find . -exec bash -c 'dosomething "{}"' \;
find
예를 들어 이름에 괄호가있는 파일과 같은 특수 문자로 인해 발생하는 모든 오류를 수정합니다 .
답변
대량 처리 결과
효율성을 높이기 위해 많은 사람들이 xargs
결과를 대량으로 처리 하는 데 사용 하지만 매우 위험합니다. 그 때문에 find
대량으로 결과를 실행 하는 대체 방법이 도입되었습니다 .
이 방법은 POSIX-의 요구 사항은, 예를 들어 같은 몇 가지주의와 함께 수도 있지만주의 find
해야하는 {}
명령의 끝에서.
export -f dosomething
find . -exec bash -c 'for f; do dosomething "$f"; done' _ {} +
find
는 많은 결과를 단일 호출에 대한 인수로 전달 bash
하고 for
-loop는 해당 인수를 반복 dosomething
하여 각 인수 에 대해 함수 를 실행합니다 .
위의 솔루션은에서 인수를 시작 $1
하므로 _
(가 나타내는 $0
)가 있습니다.
하나씩 결과 처리
같은 방법으로, 나는 받아 들여진 최고 답변이 다음과 같이 수정되어야한다고 생각합니다
export -f dosomething
find . -exec bash -c 'dosomething "$1"' _ {} \;
인수가 항상 시작해야하기 때문에,뿐만 아니라 더 제정신 $1
뿐만 아니라 사용하여 $0
파일 이름에 의해 반환 된 경우 예기치 않은 동작이 발생할 수 있습니다 find
쉘에 특별한 의미가 있습니다.
답변
스크립트를 호출하여 각 항목을 인수로 전달하십시오.
#!/bin/bash
if [ ! $1 == "" ] ; then
echo "doing something with $1"
exit 0
fi
find . -exec $0 {} \;
exit 0
스크립트를 단독으로 실행하면 찾고자하는 것을 찾고 각 찾기 결과를 인수로 전달하여 자체를 호출합니다. 스크립트를 인수와 함께 실행하면 인수에서 명령을 실행 한 다음 종료됩니다.
답변
현재 디렉토리의 모든 파일에서 주어진 명령을 실행할 bash 함수를 찾고있는 사람들을 위해 위의 답변 중 하나를 컴파일했습니다.
toall(){
find . -type f | while read file; do "$1" "$file"; done
}
공백이 포함 된 파일 이름으로 구분됩니다 (아래 참조).
예를 들어 다음 기능을 사용하십시오.
world(){
sed -i 's_hello_world_g' "$1"
}
현재 디렉토리의 모든 파일에서 hello의 모든 인스턴스를 world로 변경하고 싶다고 가정 해보십시오. 난 그럴거야:
toall world
파일 이름의 기호를 안전하게 사용하려면 다음을 사용하십시오.
toall(){
find . -type f -print0 | while IFS= read -r -d '' file; do "$1" "$file"; done
}
(하지만 GNU와 같은 find
것을 처리 해야합니다 ).-print0
find