[Linux] Bashでファイル一覧を順番に処理したい

Bashで特定のファイルを順番に処理したい場合、配列をforでぐるぐる回してやるのがお手軽です。ここでは配列listで定義した3つのファイルを順番に指定ディレクトリへコピーしています。

#!/bin/bash

# 対象のファイル一覧
list=(
  /tmp/foo.txt
  /tmp/bar.txt
  /tmp/hoge.txt
);

# 順番に処理する
for file in ${list[@]}; do
  echo "copy ${file} to /home/foo"
  cp $file /home/foo
done

一覧を別ファイルにする

別のファイルにある一覧を元にループすることも可能です。対象のファイルが大量にある場合や、コードとデータ(設定)を分離したい場合などはこちらがオススメです。

#!/bin/bash

for file in `cat list.txt`; do
  echo "copy ${file} to /home/foo"
  cp $file /home/foo
done

データファイルは以下の通り。1行に1ファイルを書くだけ。

$ cat list.txt
/tmp/foo.txt
/tmp/bar.txt
/tmp/hoge.txt

一覧を標準入力から受け取る

例えばパイプなどでリストを渡したい場合はreadコマンドを利用し、whileでループさせます。

#!/bin/bash

while read file; do
  echo "copy ${file} to /home/foo"
  cp $file /home/foo  
done

上記のシェルスクリプトcopy.shという名前で保存しました。リストとして先ほども登場したlist.txtを使用します。

$ cat list.txt
/tmp/foo.txt
/tmp/bar.txt
/tmp/hoge.txt

$ cat list.txt | ./copy.sh

一覧をコマンドの実行結果から得る

lsやfindの実行結果を対象とすることもできます。ファイル名が事前にわからない場合はこちらをどうぞ。 blog.katsubemakito.net

おまけ

エラー処理

実際に利用する場合はコマンドの実行結果も確認します。

#!/bin/bash

# 対象のファイル一覧
list=(
  /tmp/foo.txt
  /tmp/bar.txt
  /tmp/hoge.txt
);

# 順番に処理する
for file in ${list[@]}; do
  echo "copy ${file} to /home/foo"
  cp $file /home/foo

  # コピー出来なければ終了
  if [ $? -ne 0 ]; then
    echo "[Error] Can not copy file (${file})"
    exit 1;
  fi
done

実行結果は変数$?へ自動的に代入されます。Linuxではほとんどのコマンドは戻り値が0であれば正常、それ以外は何らかのエラーが発生していることを指します。

すべてのコマンドは終了時にステータス値を返す。 この値を検査することで (例えば、ほとんどのシェルでは変数 $? に最後に実行したコマンドのステータスが保持される)、 そのコマンドが成功して完了したかどうかを知ることができる。 伝統的に、終了ステータス 0 は成功を示すのに使われ、非 0 の値は そのコマンドが成功しなかったことを示す (終了ステータスの詳細は wait(2) に書かれている)。 非 0 の終了ステータスは 1 から 255 の範囲の値をとることができ、 いくつかのコマンドではコマンドが失敗した理由を示すために 複数の非 0 のステータス値が使用されている。

Linux User's Manual (1)より

参考ページ