면책조항: 저는 Unix/Linux를 처음 접하지만, 배우기를 기대하고 있습니다! 나는 이 stackexchange에서 검색을 시도하고 읽어보았지만 man find
이것을 알아낼 수 없는 것 같습니다.
find ... -exec {} +
이 명령을 사용하여 특정 파일 확장자를 가진 모든 파일을 재귀적으로 찾고 파일 목록에서 명령을 실행하고 싶습니다 . 약 100,000개의 파일을 변환해야 합니다. 내가 실행 중인 명령은 파일 이름(또는 예를 들어 파일 이름 목록 f1 f2 f3
)을 인수로 허용하지만 명령을 실행하려면 추가 인수도 지정해야 합니다.
내가 지금까지 시도한 것 :
이것은 작동합니다:
find . -iname "*.extension" -exec <command> {} <additional parameters> \;
이것은 작동하지 않는 것 같습니다:
find . -iname "*.extension" -exec <command> {} <additional parameters> +
오류 메시지가 나타납니다 find: missing argument to '-exec'
. {}
? 뒤에 다른 매개변수를 지정할 수 없는 것 같아요 .
몇 가지 참고사항:
-o <outputDir>
이 명령은 파일 이름을 첫 번째 매개 변수로 사용하고 출력 디렉터리 및 파일에서 추출할 변수 와 같은 몇 가지 추가 매개 변수를 지정해야 합니다 -v <var1,var2,...>
.
차이점이 있다면 Ubuntu 12.04의 터미널에서 이것을 실행하고 있습니다.
답변1
find . -iname "*.extension" -exec sh -c '
exec <command> "$@" <additional parameters>' sh {} +
바라보다"find ... -exec sh -c '...' sh {} +"를 사용한 find 명령은 어떻게 작동합니까?더 알아보기.
답변2
이를 통해 하나의 파일 이름 대신 공백으로 구분된 여러 파일 이름(파일이 100,000개 있으므로 긴 목록이 됨) +
이 나열됩니다 . {}
이 경우 {}
명령 끝에 나타나야 합니다.
find(1)
아래 매뉴얼 페이지를 참조하십시오 -exec command {} +
.
답변3
모든 디렉토리와 파일이 일반 이름을 가지고 있다고 가정하면(예: 공백, 개행 문자 또는 이와 유사한 문자가 포함되지 않음) 이는 엄청난 수의 파일에서도 작동합니다.
find . -iname "*.extension" -exec sh -c '
command="<command>"
additionalParameters="<additional parameters>"
h=$(($#/2))
cmd="$command "
for i in $(seq 1 $h);do
cmd="$cmd $(eval echo \$$i) "
done
cmd="$cmd $additionalParameters"
$cmd
shift $h
$command "$@" $additionalParameters' sh {} +
이유:
구두점을 사용할 때 +
find는 명령을 가능한 한 크게 만듭니다. 허용되는 최대 매개변수 수(Gnu/Linux에서는 128k여야 함)와 매개변수 목록의 최대 크기(Gnu/Linux에서는 2MB여야 함)라는 두 가지 제한 사항이 있습니다. 문제는 호출된 명령에 추가 매개변수(추가 매개변수)가 필요하다는 것입니다. 이를 추가하면 한도가 초과되어 "매개변수가 너무 많은 오류"가 발생합니다. 제가 제안한 스크립트는 구축된 매개변수 목록을 두 부분으로 나누고 블록당 하나가 아닌 두 개의 명령을 실행하므로 추가 매개변수를 추가하는 것은 문제가 되지 않습니다.
답변4
다음 스크립트를 사용할 수 있습니다.
#! /bin/bash
cmd=echo
test $# -gt 2 || exit 2
num_trailing_args="$1"
[[ $num_trailing_args =~ ^(0|[1-9][0-9]*)$ ]] ||
{ echo "Illegal first argument ('${num_trailing_args}'); aborting"; exit 2; }
test $# -lt $((num_trailing_args+2)) &&
{ echo "Too few arguments; aborting"; exit 2; }
shift
trailing_args=()
for((i=0;i<num_trailing_args;i++)); do
trailing_args[i]="$1"
shift
done
"$cmd" "$@" "${trailing_args[@]}"
그런 다음 사용
find ... -exec args_change_script.sh 3 t1 t2 t3 {} +
명령 이름은 스크립트 이름보다 길어서는 안 됩니다(확실히 말하자면).