이 루프가 빈 세트에서 실행되는 이유는 무엇입니까?

이 루프가 빈 세트에서 실행되는 이유는 무엇입니까?

빈 디렉터리를 만들고 다음 코드를 실행합니다.

find /empty_directory -mindepth 1 -maxdepth 1 -type d |
while read dir;
do
    echo "Simple find: $dir"
done

printf '%s\n' '-----'                   # Safer than    echo -----

while read dir;
do
    echo "HereDoc find: $dir"
done <<< "$(find /empty_directory -mindepth 1 -maxdepth 1 -type d)"

출력은 다음과 같습니다.

-----
HereDoc find: 

즉, 두 번째 루프는 빈 변수를 사용하여 한 번 실행됩니다.

왜 이런 일이 발생합니까? 루프오버할 디렉터리를 찾을 수 없는 경우 두 번째 루프가 제대로 작동하고 실행되지 않도록 하려면 어떻게 해야 합니까?

답변1

무슨 일이에요?

특정 문제를 해결하려고 한다는 것은 알지만 디버깅의 첫 번째 규칙 중 하나는 장면을 단순화하는 것입니다. 우리가 그렇게 한다면

$ sleep 1 | read x
$ echo "$?"
1

$ read x <<< $(sleep 1)
$ echo "$?"
0

read빈 파이프의 a는 실패하지만  null read문자열의 a는 성공합니다(null 값 읽기). 이것이 당신이 보는 것입니다.

그 철자는큰 타격(1):

여기 문자열이 있습니다

    Here 문서의 변형으로, 형식은 다음과 같습니다.

        [n]<<<word

    이것word물결표 확장, 매개변수 및 변수 확장, 명령 대체, 산술 확장 및 따옴표 제거를 수행합니다. 경로 이름 확장 및 토큰화가 수행되지 않습니다. 결과는 단일 문자열로 제공됩니다.개행 문자 추가, 표준 입력(또는 파일 설명자)의 명령에n 만약에n지정).

      (강조 추가)

Bash는 여기서 null 문자열을 EOF가 아닌 빈 줄로 변환합니다.

어떻게 고치나요?

분명한 것은 - 루프 논리를 수정한다는 것입니다:

디렉토리를 읽을 때  && ["$dir"! =“”]
하다
    echo "HereDoc 검색: $dir"
완료<<< "$(find /empty_directory -minlength1 -maxlength1 -type d)"
빈 줄을 읽으면 루프가 종료됩니다.

또한 분명한 점은 논리를 수정하는 것입니다.존재하다주기:

디렉토리를 읽을 때
하다
    if ["$dir" = ""] 다음 계속;
    echo "HereDoc 검색: $dir"
완료<<< "$(find /empty_directory -minlength1 -maxlength1 -type d)"
이는 빈 줄을 무시하지만 루프를 종료하지는 않습니다.

어쩌면 더 좋을 수도 있습니다. 리디렉션을 수정하세요.

디렉토리를 읽을 때
하다
    echo "HereDoc 검색: $dir"
완벽한<<(/empty_directory -minlength1 -maxlength1 -typed 찾기)
프로세스 대체( )와 단순 리디렉션( )을 사용하여<(command)<) 명령 대체( ) 대신 여기에는 문자열($(command)<<<), Bash가 개행을 추가하는 것을 방지할 수 있습니다.

;PS 참고로 ()를 사용하는 것처럼 줄 끝에 세미콜론을 추가할 필요는 없습니다 while read dir.

관련 정보