はじめに
現在業務で、大量にcsvを出力している作業をしています。
(※ 大量にcsvを出力している業務とは?となりますが、そこは一旦さておき...。)
そんなcsvたちを最後にBigQueryへインポートする予定ですが、100ファイル以上のcsvを手動でインポートは日が暮れても終わりません。
なので、複数のcsvファイルを1つのcsvにまとめるスクリプトを書いたので、ここにアウトプットいたします。
実装
#!/bin/bash
# 出力ファイル名
output_file="join_result.csv"
# 一時ファイル
temp_file="temp.csv"
# 既存の出力ファイルと一時ファイルを削除
rm -f "$output_file" "$temp_file"
# CSVファイルのリストを取得し、日付部分でソート
files=($(ls test_*.csv | sort -t '_' -k 3 -n))
# 最初のファイルのヘッダーを取得して出力ファイルに書き込み
head -n 1 "${files[0]}" > "$output_file"
# それ以降のファイルのデータ行を追加
for file in "${files[@]}"; do
echo "Processing $file"
# 最初の行(ヘッダー)を削除してデータを一時ファイルに追加
sed '1d' "$file" >> "$temp_file"
done
# 一時ファイルの内容を出力ファイルに追加
cat "$temp_file" >> "$output_file"
echo "CSVファイルを統合しました: $output_file"
# 一時ファイルを削除
rm -f "$temp_file"
実行コマンドは、sh join.sh
です。
解説
主な箇所を解説していきます。
files=($(ls test_*.csv | sort -t '_' -k 3 -n))
上記で、ディレクトリに格納しているcsvを取得しています。
ファイル名はtest_2018-01-01.csv
のように日付を入れています。
sort -t '_' -k 3 -n
を記述することによって、日付をソートしてくれます。
head -n 1 "${files[0]}" > "$output_file"
複数のcsvファイルは、全てヘッダーが同じとなっています。
なので、最初に取得できたファイルのヘッダーを、出力するcsvに入れています。
あとは、それぞれのファイルのヘッダーを除いた行を、一時ファイルに入れます。
最後に、まとめたら完成です。
まとめ
このシェルを使用すれば、数百ファイルを数秒で1つのcsvファイルにまとめることができます。
最初はrubyでやろうと思って作ったのですが、1行ずつ読むようにしないとできなくて、時間がものすごくかかってしまいました。
これを機に、Linux
やshell
を勉強していこうと思います。
最後までご覧いただき、ありがとうございました。