Bash 스크립트에 내장된 "read -r"이 Mac에서 다르게 동작합니다.

Bash 스크립트에 내장된 "read -r"이 Mac에서 다르게 동작합니다.

이 스크립트가 있습니다.

#!/bin/bash
function main {
  while read -r file; do
    do_something "$file"
  done <<< $(find . -type f 2>/dev/null)
}
function do_something{
   echo file:$@
}

Linux에서는 잘 작동하지만 Mac(Bash 버전 5.2)에서는 찾은 모든 파일을 하나의 항목으로 처리하고 줄 바꿈 없이 전체 문자열을 전달합니다 do_something.

  while read -r file; do
    echo file:"$file"
  done <<< $(find . -type f 2>/dev/null)

Mac의 Bash 터미널에서도 직접 잘 작동합니다. 그럼 무엇이 잘못됐나요?

답변1

이 문자열 연산자가 zsh에서 복사된 이전 버전의 bash에서는 <<< $param$((arith))$(cmdsubst)따옴표 <<<가 없는 확장이 -splitting의 영향을 받았으며 $IFS결과 단어가 공백과 연결되어 결과가 대상의 임시 파일로 전달되는 작성에 저장되었습니다.

이 문제는 4.4에서 수정되었습니다. 바라보다CWRU/변경 로그의 해당 항목:

2015-09-02

redir.c
- write_here_string: 여기서 문자열 문서를 토큰화하지 마세요. bash 문서에서는 bash가 수년 동안 이 작업을 수행해 왔고 여기에서 문자열을 구현하는 다른 쉘이 어떤 토큰화도 수행하지 않음에도 불구하고 항상 이런 일이 발생하지 않는다고 말합니다. 최종 효과는 IFS 문자 시퀀스가 ​​공백으로 축소된다는 것입니다. Clint Hepner가 보고한 버그 수정<[이메일 보호됨]>

그러나 macOS는 여전히 고대 버전의 bash를 사용합니다. 다른 곳에 최신 bash를 설치했을 수도 있지만 내가 아는 한 shebang에 사용된 /bin/bash는 5.2가 아니라 3.2.x입니다.

를 참조하면 해당 특정 문제가 해결되지만 여기서 반복 결과는 $(find...)확실히 잘못된 접근 방식입니다.find

이유와 올바른 대안을 확인하세요찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?

즉, bash루프( 에서도 사용할 수 있음 zsh)를 사용해야 하는 경우:

while IFS= read -rd '' -u3 file; do
  something with "$file"
done 3< <(find . -type f -print0 2> /dev/null)

(프로세스 교체,,,,, -rksh에서 복사된 모든 것은 -u2.05b 이전 -d또는 2.05b와 동일한 버전에 도입되었으므로 <<<macos에서 사용할 수 있어야 합니다 /bin/bash)

macos에는 zsh가 사전 설치되어 있으므로 zsh로 전환하여 다음을 작성할 수도 있습니다.

for file (**/*(ND.)) something with $file

또한보십시오:

관련 정보