이름에 공백이 있는 일부 파일이 포함된 디렉토리가 있는 경우
$ 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
파일 이름을 작성하기 위해 널 바이트 종결자를 사용하는 기본 구현이 있습니다. 이것은 여기서 고려되었지만 채택되지 않았습니다. 널 종결자를 사용한다는 것은-print0
find의 출력을 처리하려는 모든 유틸리티가 현재 읽고 있는 널 종결자를 구문 분석하기 위한 새 옵션을 추가해야 함을 의미합니다.
저것"특히Primary "는 문제를 다른 방식으로 해결하는 GNU를 의미합니다. FreeBSD도 이를 지원 합니다 -print0
.find
xargs
find
그리고xargs
. 옵션 을 추가하면 -0
(참고매뉴얼 페이지) xargs
을 호출하면 프로그램은 "널 바이트" 문자로 끝나는 줄을 허용합니다. 순서대로 xargs
호출됨구현하다- 수행할 기능그것은일하다. 함수와 함수의 주요 차이점 -print0
은 전자는 파이프를 통해 파일 이름을 전달하는 반면 후자는 그렇지 않다는 것입니다. 개발자는 거의 모든 기능의 용도를 찾을 수 있습니다. 파이프라인도 예외는 아닙니다.-0
+
OP의 예로 돌아가서 다음 -t
에서 찾을 수 없는 옵션을 사용합니다.cp
POSIX 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
예상한 대로 이름에 공백이 있는지 여부에 관계없이 모든 호출에는 파일 이름이라는 하나의 매개변수만 있습니다.