빈 디렉터리를 만들고 다음 코드를 실행합니다.
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
.