2つの条件でしばらく待機し、ディレクトリ内に複数のファイルがあるかどうかを確認します。これらの条件のいずれかがtrueの場合、ループを実行する必要があるため、通常のOR論理ステートメントです。
期待される動作とは、ディレクトリ内またはディレクトリ内の時間の順番が複数の場合、ファイルループが終了することを意味します。現在、複数のファイルをまだ待っています。誰かが私のwhileループが期待どおりに機能しない理由を私に説明できますか?
i=1; while [ $i -le 10 ] || [ $( ls /opt/hosts/ | wc -l ) -lt 2 ]; do sleep 3 $(( i++ )); done
残念ながら、1行のコマンドが必要です。なぜ私のコマンドは無限ループなのかと疑問に思っています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 ```
sleep
に2つの引数_3
_と$(( i++ ))
を指定しています。 GNUツールの場合、これはループが各反復で増加する秒数をスリープさせることを意味します。GNU以外のシステムでは、sleep
からエラーが発生します。
テストの記述方法により、ループは常に少なくとも 10回実行されます。テストでは、「_$i
_が10以下である間繰り返す」と表示されます。 _$i
_が10に達すると、テストの他の部分が有効になります。ここでは、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
_ディレクトリ内の名前の数をカウントします(ディレクトリ内の_*
_グロブを展開して数をカウントすることにより)それが展開される名前の)。名前の数が2つ以上になるか、_$i
_が値10に達すると、ループは終了します。
ループの後、_$i
_が10の場合、ファイルの具体化に失敗しました。
位置パラメーターを保持する必要がある場合(これらはset
コマンドによって上書きされます)、グロブを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
_