"find -exec"는 공백이 포함된 파일 이름을 어떻게 전달합니까?

"find -exec"는 공백이 포함된 파일 이름을 어떻게 전달합니까?

이름에 공백이 있는 일부 파일이 포함된 디렉토리가 있는 경우

$ 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사용하면 불필요한 것 같습니다 .+\;

그 이유는 무엇입니까?

답변1

명령은 find명령을 직접 실행합니다. 이 명령(filename 인수 포함)은 셸이나 파일 이름을 수정할 수 있는 다른 항목에 의해 처리되지 않습니다. 매우 안전합니다.

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

find디스크의 원래 파일 이름을 명령의 내부 매개변수 목록( -exec귀하의 경우에는 cp명령)으로 직접 전달하십시오.

답변2

질문은 두 부분으로 나누어집니다:

  • 어떻게하다 find-exec파일 이름에 공백이 포함되어 있는 문제 없이 프로그램을 호출할 수 있습니다 .
  • 이 옵션의 이점은 무엇입니까 -print0?

첫 번째 find는 실제로 다음과 같은 관련 호출 집합 중 하나인 시스템 호출을 만드는 것입니다."구현하다". 파일 이름을 이 호출에 직접 인수로 전달한 다음 파일 이름에 대한 정보를 잃지 않고 (새 프로세스를 만든 후) 호출에 직접 전달합니다.

POSIXfind특징은 +다음과 같이 설명됩니다.이유:

SVR4 유틸리티의 특징은 기본적인 + 터미네이터 find입니다 . -exec이를 통해 파일 이름에 특수 문자(특히새로운 팀문자)는 함께 그룹화되며, 이러한 파일 이름이 로 파이프되는 경우에는 발생하지 않습니다 xargs. 다른 구현에서는 이 문제를 해결하기 위해 추가 방법을 추가했으며, 특히 -print0파일 이름을 작성하기 위해 널 바이트 종결자를 사용하는 기본 구현이 있습니다. 이것은 여기서 고려되었지만 채택되지 않았습니다. 널 종결자를 사용한다는 것은 -print0find의 출력을 처리하려는 모든 유틸리티가 현재 읽고 있는 널 종결자를 구문 분석하기 위한 새 옵션을 추가해야 함을 의미합니다.

저것"특히Primary "는 문제를 다른 방식으로 해결하는 GNU를 의미합니다. FreeBSD도 이를 지원 합니다 -print0.findxargsfind그리고xargs. 옵션 을 추가하면 -0(참고매뉴얼 페이지) xargs을 호출하면 프로그램은 "널 바이트" 문자로 끝나는 줄을 허용합니다. 순서대로 xargs호출됨구현하다- 수행할 기능그것은일하다. 함수와 함수의 주요 차이점 -print0은 전자는 파이프를 통해 파일 이름을 전달하는 반면 후자는 그렇지 않다는 것입니다. 개발자는 거의 모든 기능의 용도를 찾을 수 있습니다. 파이프라인도 예외는 아닙니다.-0+

OP의 예로 돌아가서 다음 -t에서 찾을 수 없는 옵션을 사용합니다.cpPOSIX CP. 대신에 제공되는 확장("비표준 기능"이라고도 함)입니다.GNU CP. -0확장 기능은 xargs이 예제를 개선하지는 않지만 다른 상황에서 효과적으로 사용할 수 있습니다. +GNU에서 find허용하는 이식 가능한 대안이 있다는 것을 기억하십시오.

답변3

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

실험을 좋아하는 분들을 위해:

전달된 위치 인수를 나열하는 스크립트를 만들고 이름을 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

$dir 디렉토리에서 실행하세요 find:

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

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

관련 정보