Bash의 파일 경로에는 null 바이트 (제로 값 바이트 $'\0'
)를 제외한 모든 문자가 포함될 수 있으므로 null 바이트를 구분 기호로 사용하는 것이 가장 좋습니다. 예를 들어의 출력이 find
다른 프로그램으로 전송 될 경우 -print0
옵션이있는 버전 을 사용하는 것이 좋습니다 find
.
그러나 이와 같은 것이 잘 작동하지만 (줄 바꿈으로 구분 된 파일 경로 인쇄-걱정하지 마십시오. 이것은 단지 데모 일뿐입니다. 실제로 실제 스크립트에서는하지 않습니다) :
find -print0 \
| while IFS= read -r -d $'\0' ; do echo "$REPLY" ; done
이런 식으로 작동 하지 않습니다 :
for file in * ; do echo -n "$file"$'\0' ; done \
| while IFS= read -r -d $'\0' ; do echo "$REPLY" ; done
for
-loop 부분 만 시도 하면 null 바이트 없이 모든 파일 이름을 함께 인쇄한다는 것을 알았습니다 .
왜 이런거야? 무슨 일이야?
답변
Bash는 내부적으로 C 스타일 문자열을 사용하며 null 바이트로 끝납니다. 이는 Bash 문자열 (예 : 변수 값 또는 명령의 인수)이 실제로 널 바이트를 포함 할 수 없음을 의미합니다. 예를 들어이 미니 스크립트는 다음과 같습니다.
foobar=$'foo\0bar' # foobar='foo' + null byte + 'bar'
echo "${#foobar}" # print length of $foobar
실제로 인쇄 3
하기 때문에, $foobar
단지 실제로 'foo'
다음은 bar
문자열의 끝 후에 온다.
마찬가지로 부품 에 대해 알지 못 하기 때문에 echo $'foo\0bar'
그냥 인쇄합니다 .foo
echo
\0bar
보시다시피, \0
시퀀스는 실제로 $'...'
스타일 문자열 에서 매우 오도됩니다 . 문자열 내부의 null 바이트처럼 보이지만 그런 식으로 작동하지 않습니다. 첫 번째 예에서 read
명령은 -d $'\0'
입니다. 이것은 작동하지만 작동하기 때문에 만 가능 -d ''
합니다! (즉의 명시 적으로 문서화 기능이 아니다 read
, 그러나 나는 같은 이유로 작동 가정 : ''
빈 문자열이, 그 종료 널 바이트가 바로 온다 그래서. “의 첫 번째 문자 사용으로 설명되어 있습니다 DELIM를 “나는 심지어 작품을 추측 “첫 번째 문자”가 문자열의 끝을 지났다면!)-d delim
당신이 알고 그러나 find
예, 그것은 이다 명령이 널 바이트를 출력하고, 그 바이트가 입력으로 읽고 다른 명령에 파이프 할 할 할 수 있습니다. 그중 어느 것도 Bash 내부의 문자열에 null 바이트를 저장하는 것에 의존하지 않습니다 . 두 번째 예의 유일한 문제 $'\0'
는 명령에 대한 인수로 사용할 수 없다는 것 입니다. echo "$file"$'\0'
원하는 경우에만 null 바이트를 행복하게 인쇄 할 수 있습니다.
따라서을 사용하는 대신 스타일 문자열 과 동일한 종류의 이스케이프 시퀀스를 지원하는을 echo
사용할 수 있습니다 . 이렇게하면 문자열 안에 null 바이트가 없어도 null 바이트를 인쇄 할 수 있습니다. 다음과 같이 보일 것입니다.printf
$'...'
for file in * ; do printf '%s\0' "$file" ; done \
| while IFS= read -r -d '' ; do echo "$REPLY" ; done
또는 단순히 이것 :
printf '%s\0' * \
| while IFS= read -r -d '' ; do echo "$REPLY" ; done
(참고 : echo
실제로 널 바이트를 -e
처리 \0
하고 인쇄 할 수 있는 플래그가 있지만 파일 이름의 특수 시퀀스를 처리하려고 시도하므로 printf
접근 방식 이보다 강력합니다.)
덧붙여, 어떤 조개가 않습니다 null의 내부 문자열을 바이트 수 있습니다. 예를 들어 Zsh에서는 기본 설정을 가정하여 정상적으로 작동합니다. 그러나 쉘과 상관없이 Unix와 같은 운영 체제는 프로그램에 대한 인수 내부에 널 바이트를 포함시키는 방법을 제공하지 않으므로 (프로그램 인수가 C 스타일 문자열로 전달되므로) 항상 제한이 있습니다. (이 예제는 echo
쉘이 내장되어 있기 때문에 Zsh에서만 작동 할 수 있으므로 Zsh는 다른 프로그램을 호출하기 위해 OS 지원에 의존하지 않고 호출 할 수 있습니다. command echo
대신에 사용 echo
하면 내장 echo
프로그램을 무시하고에서 독립 실행 형 프로그램을 사용했습니다 $PATH
. Zsh에서 Bash와 동일한 동작을 볼 수 있습니다.)