
オンラインでforループの例を見つけました。私は私のコードでこれを使いたいのですが、このループがどのように機能するのかわかりません。
for entry in "$search_dir"/*
do
echo "$entry"
done
今私は聞きたいです。
- 反復ごとにsearch_dirを検索し、search_dirのファイルを各反復ごとに1つの項目変数のファイルにコピーしますか?
- それとも、search_dirのすべてのコンテンツのスナップショットを撮ってから、そのスナップショットをアイテム変数に保存しますか?
- ループが動作し続けている間、誰かがsearch_dirにいくつかのファイルを挿入すると、出力は変わりますか?
答え1
シェルがfor
- ステートメントに到達すると、値を展開して$search_dir
ファイル名のグロービングを実行して、繰り返すディレクトリエントリのリストを生成します。これは一度だけ発生します。ループの内容が$search_dir
消えたり、新しいファイル/ディレクトリがディレクトリに追加されても、その変更は適用されません。
ループが名前付きディレクトリエントリで動作している場合は、その$entry
エントリがループ内に存在するかどうかをテストできます。特に、ループの実行に長い時間がかかり、次のような理由で絶えず変更される多数のファイルがある場合は、さらにそうです。もう一つ:
for entry in "$search_dir"/*; do
if [ -e "$entry" ]; then
# operate on "$entry"
else
# handle the case that "$entry" went away
fi
done
Stéphaneがコメントで正しく指摘したように、これは重複するテストです。最大ケース。
答え2
シェルは、ループ本文の実行を開始する前にループする値のリストを完全に決定します。それは:
- シェルは変数の値を使用してパスを作成します
search_dir
。 - シェルは、指定されたディレクトリからファイル名のリストを収集して、一致するワイルドカードパターンのリストを作成します。
- シェルは、一致するリストの各要素に対してループ本体を順番に実行します。
search_dir
ループの実行中に変数の値を変更したり、ディレクトリの内容を変更したりできます。これはループが動作するファイルには影響しません。
他のファイルを繰り返しながらファイルを削除する場合、ファイルに到達するとそのファイルは存在しません。ループで何をするかに応じて、これは重要でも重要ではないかもしれません。ファイルを削除できる同時プロセスがある場合は、処理前にファイルが存在するかどうかをテストするだけでは問題が実際に解決されないことに注意してください。テスト後の処理の開始間にファイルが削除されることがあります。。
ファイルが2回処理されないように処理済みとしてマークする必要がある場合、このスクリプトはファイルが処理された後にファイルを別のディレクトリに移動する必要があります。同じファイルシステムの別のディレクトリにファイルを移動する原子: まだ完了していないか、すでに完了しており、中間状態はありません。しかし、もしその他プロセス(おそらくスクリプトの他のインスタンス)がファイルを移動すると、ループの実行中に移動したファイルにループがクラッシュすることがあります。
新しいファイルが作成されたときにそれを処理するには、もう一度繰り返す必要があります。明らかに、ループの実行中または以前のすべてのファイルが処理された後にファイルが生成される可能性があるため、スクリプトの実行に時間がかかります。ディレクトリにファイルが作成されるのを待つことができるツールがあります。 Linuxでは、基本的な機能は次のとおりです。inotify;ファイルの作成時にファイルを処理する必要がある場合inotifywait
またはインクロンあなたを助ける必要があります。 inotifyは、生成された(またはトリガーに応じて変更またはアクセスされた)ファイルのみを通知することを覚えておいてください。後ろにInotifyベースのコマンドの実行。既存のファイルも処理する必要がありますが、for entry in *; do …; done; inotifywait …
ループ実行中またはコマンドinotifywait
実行時にファイルが生成される可能性があるため、そうすることはできません。