답변:
쉘만이 쉘 함수를 실행하는 방법을 알고 있으므로 함수를 실행하려면 쉘을 실행해야합니다. 또한로 내보내기를 위해 함수를 표시해야합니다 export -f
. 그렇지 않으면 서브 쉘이이를 상속하지 않습니다.
export -f dosomething
find . -exec bash -c 'dosomething "$0"' {} \;
find . -exec bash -c 'dosomething "$0"' {} \;
그것을 사용 하면 파일 이름에서 공백 (및 다른 이상한 문자)을 처리합니다 ...
export -f
bash는 일부 버전에서만 작동합니다. 크로스 플랫폼이 아닌 posix가 아니며 /bin/sh
오류가 발생합니다.
find . | while read file; do dosomething "$file"; done
while read
for 루프를 변경 하여 문제를 해결했습니다 . for item in $(find . ); do some_function "${item}"; done
위의 Jak의 대답은 훌륭하지만 쉽게 극복 할 수있는 몇 가지 함정이 있습니다.
find . -print0 | while IFS= read -r -d '' file; do dosomething "$file"; done
줄 바꿈 대신 구분 기호로 null을 사용하므로 줄 바꿈이있는 파일 이름이 작동합니다. 또한 -r
파일 이름의 백 슬래시가 작동하지 않으면 백 슬래시 이스케이프를 비활성화 하는 플래그를 사용합니다. 또한 IFS
이름의 잠재적 인 후행 공백이 삭제되지 않도록 지 웁니다 .
/bin/bash
좋지만 작동하지 않습니다 /bin/sh
. 안타까워 라.
{}
아래와 같이 따옴표를 추가하십시오 .
export -f dosomething
find . -exec bash -c 'dosomething "{}"' \;
find
예를 들어 이름에 괄호가있는 파일과 같은 특수 문자로 인해 발생하는 모든 오류를 수정합니다 .
{}
. 큰 따옴표가 포함 된 파일 이름이 손상됩니다. touch '"; rm -rf .; echo "I deleted all you files, haha
. 죄송합니다.
-exec bash -c 'echo $0' '{}' \;
을 사용할 때 bash -c
$ 0은 스크립트 이름이 아닌 첫 번째 인수입니다.
효율성을 높이기 위해 많은 사람들이 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
스크립트를 단독으로 실행하면 찾고자하는 것을 찾고 각 찾기 결과를 인수로 전달하여 자체를 호출합니다. 스크립트를 인수와 함께 실행하면 인수에서 명령을 실행 한 다음 종료됩니다.
find: ‘myscript.sh’: No such file or directory
시작 하면 실패합니다 bash myscript.sh
...
현재 디렉토리의 모든 파일에서 주어진 명령을 실행할 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
그런 식으로 함수 를 실행할 수는 없습니다 .
이것을 극복하기 위해 쉘 스크립트에 함수를 넣고 다음에서 호출 할 수 있습니다 find
# dosomething.sh
dosomething () {
echo "doing something with $1"
}
dosomething $1
이제 다음과 같이 찾으십시오.
find . -exec dosomething.sh {} \;
dosomething $1
dosomething "$1"
find . -exec bash dosomething.sh {} \;
다른 답변에 대한 추가 및 설명을 제공하려면 exec
또는 execdir
( -exec command {} +
)에 대량 옵션을 사용하고 모든 위치 인수를 검색하려는 경우 $0
with 처리를 고려해야합니다 bash -c
. 보다 구체적으로, bash -c
위에서 제안한대로 사용하는 아래 명령을 고려하고 찾은 각 디렉토리에서 '.wav'로 끝나는 파일 경로를 에코합니다.
find "$1" -name '*.wav' -execdir bash -c 'echo $@' _ {} +
bash 매뉴얼은 다음과 같이 말합니다.
If the -c option is present, then commands are read from the first non-option argument command_string. If there are arguments after the command_string, they are assigned to the
positional parameters, starting with $0.
여기, 'check $@'
명령 문자열이 있으며 명령 문자열 _ {}
뒤의 인수입니다. 참고 $@
모든 위치 매개 변수로 확장가 떠들썩한 파티에서 특별한 위치 매개 변수 1부터 시작이 . 또한 -c
옵션을 사용하면 첫 번째 인수가 위치 매개 변수에 지정됩니다 $0
. 이는로 모든 위치 매개 변수에 액세스하려고하면 $@
시작 $1
및 시작하는 매개 변수 만 가져 옵니다. 이것이 Dominik의 답변에 _
매개 변수를 채우는 더미 인수 인을 갖는 이유 $0
이므로 원하는 모든 인수는 $@
예를 들어 매개 변수 확장을 사용 하거나 해당 루프에서 for 루프를 사용하면 나중에 사용할 수 있습니다 .
물론 허용 된 답변과 마찬가지로 bash -c 'shell_function $0 $@'
명시 적으로 전달하여 작동 $0
하지만 다시 $@
예상대로 작동하지 않는다는 것을 명심해야합니다 .
$0
.