‘find -exec’는 공백으로 파일 이름을 어떻게 전달합니까? dir2 {} + 그러나 출력 find

이름에 공백이있는 파일이 들어있는 디렉토리가있는 경우

$ ls -1 dir1
file 1
file 2
file 3

다음과 같이 다른 디렉토리에 모두 복사 할 수 있습니다.

$ find dir1 -mindepth 1 -exec cp -t dir2 {} +

그러나 출력 find dir1 -mindepth 1에는 이스케이프되지 않은 공백이 포함됩니다.

$ find dir1 mindepth 1
dir1/file 1
dir1/file 3
dir1/file 3

print0대신에 사용 print하면 출력에는 여전히 이스케이프되지 않은 공백이 포함됩니다.

$ find dir1 mindepth 1 -print0
dir1/file 1dir1/file 2dir1/file 3

을 사용하여 이러한 파일을 수동으로 복사하려면 cp공백을 이스케이프 처리해야합니다. 그러나 내가 명령을 사용하는지 또는 명령의 끝에 있는지에 관계없이 cp의 주장이 나올 때 이것은 불필요 해 보인다 .find+\;

그 이유는 무엇입니까?



답변

find명령 직접 명령을 실행한다. 파일 이름 인수를 포함한 명령은 셸이나 파일 이름을 수정할 수있는 다른 방법으로 처리되지 않습니다. 매우 안전합니다.

명령 행 {}에 표시된 파일 이름을 이스케이프 할 필요가없는 것이 맞습니다 find.

find원시 파일 이름을 디스크에서 직접 -exec명령 의 내부 인수 목록으로 전달합니다 (이 경우 cp명령).


답변

문제는 두 부분으로 구성됩니다.

  • 어떻게 않습니다 find 사용하여 전화 프로그램에 관리 -exec파일 이름에 공백이 문제로 실행하지 않고, 및
  • -print0옵션 은 무엇 입니까?

첫 번째 find는 실제로 “exec” 라고하는 관련 호출 그룹 중 하나 인 시스템 호출 입니다. 파일 이름에 대한 정보를 잃지 않고 파일 이름을이 호출에 직접 인수로 전달한 다음 새 프로세스를 작성한 후 직접 전달합니다.

POSIX find기능 +이론적 근거 로 다음과 같이 설명됩니다 .

SVR4 find유틸리티 의 기능은 -exec1 차 + 터미네이터였습니다. 이를 통해 특수 문자 (특히 개행 문자)가 포함 된 파일 이름을 파일 이름으로 파이프하는 경우 발생하는 문제없이 그룹화 할 수 있습니다 xargs. 다른 구현에서는이 문제를 해결하기위한 다른 방법, 특히 -print0null 바이트 종결자가있는 파일 이름을 쓴 기본 방법이 추가되었습니다 . 이것은 여기에서 고려되었지만 채택되지는 않았습니다. null 종결자를 사용한다는 것은 find의 -print0출력 을 처리하려는 모든 유틸리티 가 현재 읽고있는 null 종결자를 구문 분석하는 새로운 옵션을 추가해야 한다는 것을 의미했습니다
.

그것은 ” 특히-print0 차”는 GNU를 의미 find하고 xargs있는 다른 방법으로 문제를 해결한다. 또한 FreeBSD find및 에서도 지원됩니다 xargs. 호출에 -0옵션 ( 매뉴얼 페이지 참조 )을 추가 한 경우 xargs해당 프로그램은 “널 바이트”문자로 끝나는 행을 승인합니다. 차례로 exec -functions를 xargs호출 하여 작업 을 수행 합니다 . 와 피처 와 피처 의 주요 차이점 은 전자가 파이프를 통해 파일 이름을 전달하지만 후자는 그렇지 않습니다. 개발자는 거의 모든 기능에 대한 용도를 찾습니다. 파이프도 예외는 아닙니다.-print0-0+

POSIX cp 에는없는 -t옵션을 사용하는 OP의 예로 돌아갑니다 . 그보다는 GNU cp에서 제공하는 확장 (일명 “비표준 기능”) 입니다. 의 확장은 이 예제를 개선 시키지는 않지만 효과적으로 사용할 수있는 다른 경우가 있습니다 . GNU가 받아 들일 수 있는 이식 가능한 대안이 있다는 것을 명심하십시오 .cp-0xargs+find


답변

( 이것은 주석이어야하지만 너무 큽니다. )

시도해보고 싶은 사람들을 위해 :

전달 된 위치 매개 변수를 나열하는 스크립트를 작성하고이를 호출하십시오 list_positional_parameters.sh.

#!/bin/bash

# http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.html
# Try globbing patterns, e.g. "X[[:digit:]][[:digit:]]" to see what happens

if [ $# -lt 1 ]; then
   echo "Usage: $0 and then at least one parameter"
   exit 1
fi

counter=1

while (($#)); do
   echo "$counter = '$1'"
   # pop positional argument 1 off the stack of positional arguments
   shift
   (( counter++ ))
done

find$ dir 디렉토리에서 실행하십시오 .

find "$dir" -exec ./list_positional_parameters.sh '{}' ';' | less

예상 한대로 이름에 공백이 있는지 여부에 관계없이 모든 호출에 파일 이름 인 단일 매개 변수 만 있습니다.


답변