잠시 기다렸다가 디렉터리에 여러 파일이 있는지 확인하는 두 가지 조건이 있습니다. 이러한 조건 중 하나가 true이면 루프를 실행해야 하므로 정상적인 OR 논리문입니다.
예상되는 동작은 시간이 경과하거나 디렉터리에 파일이 두 개 이상 있으면 루프가 종료됨을 의미합니다. 하나 이상의 문서가 아직 대기 중입니다. 누군가 내 while 루프가 예상대로 작동하지 않는 이유를 설명할 수 있습니까?
i=1; while [ $i -le 10 ] || [ $( ls /opt/hosts/ | wc -l ) -lt 2 ]; do sleep 3 $(( i++ )); done
불행히도 한 줄 명령이 필요합니다. 내 명령이 왜 OR이 예상대로 작동하지 않는 무한 루프인지 알고 싶습니다. (첫 번째 조건을 3으로 변경했습니다.)
+ echo host_name
+ i=1
+ '[' 1 -le 2 ']'
+ sleep 1 1
+ '[' 2 -le 2 ']'
+ sleep 1 2
+ '[' 3 -le 2 ']'
++ ls /opt/hosts/
++ wc -l
+ '[' 1 -lt 2 ']'
+ sleep 1 3
+ '[' 4 -le 2 ']'
++ ls /opt/hosts/
++ wc -l
+ '[' 1 -lt 2 ']'
+ sleep 1 4
+ '[' 5 -le 2 ']'
++ ls /opt/hosts/
++ wc -l
+ '[' 1 -lt 2 ']'
+ sleep 1 5 ```
답변1
sleep
두 개의 매개변수를 제공3
하고$(( i++ ))
. GNU 도구의 경우 이는 반복할 때마다 루프가 휴면 상태에 있는 시간(초)이 증가함을 의미합니다. GNU가 아닌 시스템에서는sleep
.루프는 항상 실행됩니다적어도테스트 작성 방법에 따라 10번. 테스트에 "
$i
10보다 작거나 같은 반복"이라고 표시됩니다. 10에 도달 하면$i
테스트의 다른 부분이 적용됩니다. 여기서는 OR 대신 논리적 AND 테스트를 수행할 수 있습니다.ls | wc -l
디렉토리의 파일 수를 계산하는 데 사용해서는 안됩니다 . 일부(병리적이긴 하지만) 경우 이는 잘못된 결과를 초래할 수 있습니다.
대신에:
i=1
while [ "$i" -ne 10 ]; do
set -- /opt/hosts/*
if [ "$#" -ge 2 ]; then
break
fi
sleep 3 # or, to sleep longer and longer: sleep "$(( 3 + i ))"
i=$(( i + 1 ))
done
이는 i
각 반복마다 적절하게 증가하며 디렉터리의 이름 수를 계산하는 보다 안전한 방법을 사용합니다 /opt/hosts
(디렉토리에서 glob을 확장 *
하고 확장된 이름 수를 계산하여). 이름 수가 2개 이상이거나 $i
값이 10에 도달할 때마다 루프가 종료됩니다.
루프 후 $i
10이면 파일이 구체화되지 않은 것입니다.
위치 인수( 명령에 의해 재정의됨 set
)를 유지해야 하는 경우 를 사용하는 대신 glob을 배열로 확장한 names=( /opt/hosts/* )
다음 "${#names[@]}"
해당 배열의 길이를 가져옵니다 "$#"
.
당신은 또한 쓸 수 있습니다
i=1
while [ "$i" -ne 10 ] && ( set -- /opt/hosts/*; [ "$#" -lt 2 ] )
do
sleep 3
i=$(( i + 1 ))
done
set
이는 서브셸에서 실행하는 기존 위치 인수를 삭제하지 않습니다 . 그것은 또한 당신이 직접 시도해 본 유형에 더 가깝습니다.
"한 줄"로:
i=1; while [ "$i" -ne 10 ]; do set -- /opt/hosts/*; [ "$#" -ge 2 ] && break; sleep 3; i=$(( i + 1 )); done
또는 "산술 for
루프"를 사용하십시오 bash
.
for (( i=1; i<=10; i++ )); do set -- /opt/hosts/*; [ "$#" -ge 2 ] && break; sleep 3; done
또는 구분선 위의 마지막 코드 부분을 사용하세요.
i=1; while [ "$i" -ne 10 ] && ( set -- /opt/hosts/*; [ "$#" -lt 2 ] ); do sleep 3; i=$(( i + 1 )); done