何よりもまず、名前の変更はアトミックです。ファイルを 2 回移動することはできません。ファイルが存在しないため、移動の 1 つが失敗します。スクリプトが並行して実行される場合、両方とも同じ 10 個のファイルをリストし、最初の 10 個のファイルが に移動され/tmp/task1
、次の 10個のファイルが に移動されるのではなく、 /tmp/task2
4 個が に移動され/tmp/task1
、6 個が に移動される場合があります/tmp/task2
。あるいは、5 と 5、9 と 1、またはその他の組み合わせかもしれません。しかし、各ファイルは 1 つのタスクで終わるだけです。
したがって、何も間違っていません。各ファイルは 1 回だけ処理されます。ただし、一度に 10 個のファイルを処理できますが、5 個しか処理していないため、非効率的です。使用可能なファイルが十分にある場合に常に 10 個を処理するようにしたい場合は、同期を行う必要があります。基本的に 2 つのオプションがあります。
リスト+コピーの周りにロックを配置します。flock
これは、 (1)とロック ファイルを使用して最も簡単に実行できます。それを呼び出す方法も 2 つあります。
flock を介してコピー操作全体を呼び出します。
flock targdir -c copy-script
これには、除外する必要がある部分を別のスクリプトにする必要があります。
ファイル記述子によるロック。コピーする前に、
exec 3>targdir/.lock
flock 3
そしてそれがした後
flock -u 3
これにより、スクリプトの一部のみをロックできます。これは Cygwin では機能しません (しかし、おそらく必要ないでしょう)。
十分な量になるまで、ファイルを 1 つずつ移動します。
ls -1h targdir/*.json > ${TMP_LIST_FILE}
# ^^^ do NOT limit here
COUNT=0
while read REMOTE_FILE
do
if mv $REMOTE_FILE $SCRDRL 2>/dev/null; then
COUNT=$(($COUNT + 1))
fi
if [ "$COUNT" -ge "$LIMIT" ]; then
break
fi
done < "${TMP_LIST_FILE}"
rm -f "${TMP_LIST_FILE}"
が失敗することがあります。その場合、ファイルが他のスクリプトによって移動されたために失敗したmv
と仮定して、ファイルをカウントせずに次のファイルを移動しようとします。mv
各スクリプトは多くのファイルをコピーし$LIMIT
ますが、ランダムに選択される場合があります。
while
余談ですが、ループで環境変数を設定する必要がまったくない場合は、一時ファイルなしで実行できます。単に:
ls -1h targdir/*.json | while read REMOTE_FILE
do
...
done
パイプラインの一部としてサブシェルで実行されるため、このようなループから変数を伝播することはできません。
環境変数を設定する必要があり、特にbashを使用して生活できる場合(私は通常、に固執しようとし/bin/sh
ます)、次のように書くこともできます
while read REMOTE_FILE
do
...
done <(ls -1h targdir/*.json)
この場合、ループは現在のシェルで実行されますが、この種のリダイレクトは bash 拡張です。