質問: POSIX shell (あるいは Dash) のシェルスクリプトにおいて `.txt` という拡張子を末尾に持つファイルたち全てに対して何らかの処理がしたいとき、どのように書けますか? たとえば全てのファイル名を出力するにはどうすれば良いですか? ただし、以下を全て満たしたいです。 * ファイル名に空白が入っていても良い。 * ファイル名に改行が入っていても良い。 * ディレクトリは除きたい。それ以外はシンボリックリンクも含め全てそのまま扱いたい。 * 条件に合うファイルが無い場合、何もしない。
回答: glob を使ってファイルたちを見つけ出し、for 文を回せば良いです。 ``` for file in *.txt ; do [ -f "$file" ] || continue # 実行したいコマンド echo "$file" done ``` ディレクトリも含めたい場合は、`-f` でなく `-e` を使ってください。 以下、注意事項です。 * この方法では `.piyo.txt` のようなファイルは捕捉されません。ドットから始まるファイルも捕捉したい場合、`.*.txt` というパターンを使うとマッチすることができます。 * `*.txt` にマッチするファイルが無かった場合、`$file` には `*.txt` という文字列そのものが代入されてしまいます。しかし ` -f "$file" ]` でそのファイルが存在しているかどうか確認しているので問題ありません。また Bash の場合は、`shopt -s nullglob` を使うことで[この問題を回避できます。 * この方法はファイルたちを一旦列挙してから 1 つずつ処理するため、`.txt` ファイルがあまりにも多い場合はメモリ容量に関するエラーが出るかもしれません。そうならないような方法については 774RR さんの回答をご覧ください。 * `*.txt` の代わりに `$(ls *.txt)` を使ってしまうと、空白が含まれたファイル名を正しく処理できません。