Linuxで作業していると 「2つのファイルを1つにまとめたい」 という場面がよくあります。
例えば、
- 複数のログを1つにまとめたい
- 2つのCSVを横にくっつけたい
- 共通キーでマージしたい
など。Linuxにはこれを簡単に行うための便利なコマンドがたくさんあります。
この記事では代表的な
- cat(縦に結合)
- paste(横に結合)
- join(共通キーで結合)
の使い方をわかりやすく紹介します。
ファイル結合の基本概念

結合方法の種類
縦結合(Vertical Concatenation)
- ファイルの内容を上下につなげる
- 行数が増える(列数は変わらない)
- ログファイルの統合などに使用
横結合(Horizontal Concatenation)
- ファイルの内容を左右につなげる
- 列数が増える(行数は基本的に変わらない)
- データの項目を追加する場合に使用
キーベース結合(Key-based Join)
- 共通のキー(ID)をもとに関連データを結合
- データベースのJOIN操作と同じ概念
- リレーショナルデータの処理に使用
よくある使用場面
ログファイルの管理
- 複数日のログを1つにまとめる
- 異なるサービスのログを時系列で統合
- エラーログと通常ログの結合
データ分析
- CSVファイルの列を追加
- 実験データと設定データの結合
- 統計データの統合
システム管理
- 設定ファイルの統合
- バックアップファイルの結合
- レポートファイルの作成
cat でファイルを縦に結合する
基本的な使い方
cat の語源と役割 cat
は「concatenate(連結する)」の略で、複数ファイルを行をつなげて1つのファイルにするのに最適です。
基本構文:
cat file1.txt file2.txt > combined.txt
実際の例
サンプルファイルの準備:
# file1.txt の内容
echo -e "ログ開始\n2024-01-15 10:00 システム起動\n2024-01-15 10:01 サービス開始" > file1.txt
# file2.txt の内容
echo -e "2024-01-15 11:00 ユーザーログイン\n2024-01-15 11:30 処理完了\nログ終了" > file2.txt
縦結合の実行:
cat file1.txt file2.txt > combined.txt
結果:
ログ開始
2024-01-15 10:00 システム起動
2024-01-15 10:01 サービス開始
2024-01-15 11:00 ユーザーログイン
2024-01-15 11:30 処理完了
ログ終了
追記による結合
既存ファイルに追記:
cat file2.txt >> file1.txt
これで file2.txt
の内容が file1.txt
の末尾に追記されます。
区切り文字を挿入した結合:
cat file1.txt <(echo "--- 区切り線 ---") file2.txt > combined.txt
複数ファイルの一括結合
3つ以上のファイル:
cat file1.txt file2.txt file3.txt > all_combined.txt
ワイルドカードを使用:
cat log_*.txt > all_logs.txt
番号付きの結合:
cat -n file1.txt file2.txt > numbered_combined.txt
実用的な活用例
日別ログの統合:
cat access.log.2024-01-{01..31} > january_access.log
設定ファイルの結合:
cat header.conf main.conf footer.conf > complete.conf
CSVファイルのデータ統合:
# ヘッダーを保持しつつデータ部分を結合
head -n 1 data1.csv > combined.csv
tail -n +2 data1.csv data2.csv data3.csv >> combined.csv
paste でファイルを横に結合する

基本的な使い方
paste の役割 paste
は複数ファイルを行ごとに横に並べるコマンドです。
基本構文:
paste file1.txt file2.txt
実際の例
サンプルファイルの準備:
# names.txt
echo -e "Alice\nBob\nCharlie" > names.txt
# ages.txt
echo -e "25\n30\n35" > ages.txt
# cities.txt
echo -e "Tokyo\nOsaka\nKyoto" > cities.txt
基本的な横結合:
paste names.txt ages.txt
結果(タブ区切り):
Alice 25
Bob 30
Charlie 35
区切り文字のカスタマイズ
カンマ区切りで結合:
paste -d ',' names.txt ages.txt cities.txt
結果:
Alice,25,Tokyo
Bob,30,Osaka
Charlie,35,Kyoto
複数の区切り文字を使用:
paste -d ',|' names.txt ages.txt cities.txt
結果:
Alice,25|Tokyo
Bob,30|Osaka
Charlie,35|Kyoto
高度な paste オプション
縦方向の結合(-s オプション):
paste -s names.txt
結果:
Alice Bob Charlie
1つのファイルの列を分割:
# data.txt が "name:age:city" 形式の場合
tr ':' '\n' < data.txt | paste -d ',' - - -
実用例
CSVファイルの列追加:
# 既存CSVに新しい列を追加
paste -d ',' existing_data.csv new_column.txt > updated_data.csv
ログファイルの対比:
# 2つのサーバーのログを並べて比較
paste server1.log server2.log | head -20
数値データの集計準備:
# 複数ファイルの数値データを横に並べる
paste -d ' ' values1.txt values2.txt values3.txt | awk '{print $1+$2+$3}'
join で共通キーをもとに結合する
基本的な使い方
join の役割 join
は2つのファイルを共通のキーでマッチさせて横に結合します。データベースのJOIN操作と同じ概念です。
重要な前提条件:
- 両方のファイルがソートされている必要があります
- デフォルトでは1列目をキーにします
実際の例
サンプルファイルの準備:
# products.txt (商品ID 商品名)
echo -e "1 Apple\n2 Banana\n3 Orange" | sort > products.txt
# prices.txt (商品ID 価格)
echo -e "1 100\n2 80\n3 120" | sort > prices.txt
基本的な結合:
join products.txt prices.txt
結果:
1 Apple 100
2 Banana 80
3 Orange 120
高度な join オプション
異なる列をキーに指定:
# file1の2列目とfile2の1列目で結合
join -1 2 -2 1 file1.txt file2.txt
区切り文字の指定:
# CSVファイルの結合
join -t ',' file1.csv file2.csv
外部結合(LEFT JOIN):
# file1のすべての行を保持
join -a 1 file1.txt file2.txt
外部結合(RIGHT JOIN):
# file2のすべての行を保持
join -a 2 file1.txt file2.txt
完全外部結合(FULL JOIN):
# 両方のファイルのすべての行を保持
join -a 1 -a 2 file1.txt file2.txt
実用的な join 活用例
売上データと商品マスタの結合:
# sales.txt: 商品ID 数量 日付
# products.txt: 商品ID 商品名 単価
sort sales.txt > sales_sorted.txt
sort products.txt > products_sorted.txt
join sales_sorted.txt products_sorted.txt > sales_with_products.txt
ユーザー情報の統合:
# users.txt: ユーザーID 名前
# orders.txt: ユーザーID 注文番号 金額
join -t ',' users.txt orders.txt > user_orders.txt
複雑なキーでの結合:
# 複数列をキーとする場合(事前に結合キーを作成)
awk '{print $1"-"$2, $0}' file1.txt | sort > file1_keyed.txt
awk '{print $1"-"$2, $0}' file2.txt | sort > file2_keyed.txt
join file1_keyed.txt file2_keyed.txt | cut -d' ' -f2- > result.txt
高度なファイル結合テクニック

awk を使った柔軟な結合
条件付き結合:
# 特定条件でファイルを結合
awk 'FNR==NR{a[NR]=$0; next} {print a[FNR], $0}' file1.txt file2.txt
複雑な形式のファイル結合:
# ヘッダー付きCSVの結合
awk '
FNR==1 && NR==1 {print $0; next}
FNR==1 {next}
{print}
' file1.csv file2.csv file3.csv > combined.csv
sort と組み合わせた結合
結合前のソート:
# join 用の事前ソート
sort -k1,1 file1.txt > file1_sorted.txt
sort -k1,1 file2.txt > file2_sorted.txt
join file1_sorted.txt file2_sorted.txt > joined.txt
数値キーでのソート:
sort -k1,1n file1.txt > file1_sorted.txt # 数値ソート
sort -k1,1n file2.txt > file2_sorted.txt
join file1_sorted.txt file2_sorted.txt > joined.txt
大きなファイルの効率的な結合
メモリ効率を考慮した結合:
# 大きなファイルの場合、sort の一時ファイルを活用
sort -T /tmp file1.txt > file1_sorted.txt
sort -T /tmp file2.txt > file2_sorted.txt
join file1_sorted.txt file2_sorted.txt > result.txt
ストリーミング処理:
# パイプを使ったリアルタイム結合
mkfifo pipe1 pipe2
sort file1.txt > pipe1 &
sort file2.txt > pipe2 &
join pipe1 pipe2 > result.txt
エラーハンドリングとトラブルシューティング
よくあるエラーと対処法
join でソートされていないエラー:
# エラー例
join: file1.txt:2: is not sorted
# 対処法
sort file1.txt > file1_sorted.txt
sort file2.txt > file2_sorted.txt
join file1_sorted.txt file2_sorted.txt
文字コードの問題:
# 文字コード変換後に結合
iconv -f SHIFT_JIS -t UTF-8 file1.txt > file1_utf8.txt
iconv -f SHIFT_JIS -t UTF-8 file2.txt > file2_utf8.txt
cat file1_utf8.txt file2_utf8.txt > combined.txt
ファイルサイズの不一致(paste):
# 行数が違うファイルのpaste
paste file1.txt <(cat file2.txt; yes "" | head -n 10) > result.txt
デバッグとテスト
結合前の確認:
# ファイルの行数確認
wc -l file1.txt file2.txt
# ファイルの先頭確認
head -5 file1.txt file2.txt
# キー列の重複確認
cut -d' ' -f1 file1.txt | sort | uniq -d
結合結果の検証:
# 結合後の行数確認
wc -l combined.txt
# 結合後の列数確認
awk '{print NF; exit}' combined.txt
実用的なスクリプト例
汎用ファイル結合スクリプト
file_combiner.sh:
#!/bin/bash
# ファイル結合スクリプト
show_help() {
cat << EOF
使用法: $0 [オプション] file1 file2 [output]
オプション:
-v, --vertical 縦結合(cat)
-h, --horizontal 横結合(paste)
-j, --join キー結合(join)
-d, --delimiter 区切り文字指定
-k, --key キー列指定(join用)
--help このヘルプを表示
例:
$0 -v file1.txt file2.txt combined.txt
$0 -h -d ',' file1.csv file2.csv result.csv
$0 -j -k 1 file1.txt file2.txt joined.txt
EOF
}
# デフォルト値
MODE="vertical"
DELIMITER=""
KEY_COL="1"
OUTPUT=""
# オプション解析
while [[ $# -gt 0 ]]; do
case $1 in
-v|--vertical)
MODE="vertical"
shift
;;
-h|--horizontal)
MODE="horizontal"
shift
;;
-j|--join)
MODE="join"
shift
;;
-d|--delimiter)
DELIMITER="$2"
shift 2
;;
-k|--key)
KEY_COL="$2"
shift 2
;;
--help)
show_help
exit 0
;;
-*)
echo "未知のオプション: $1"
show_help
exit 1
;;
*)
break
;;
esac
done
# ファイル引数の確認
if [ $# -lt 2 ]; then
echo "エラー: 最低2つのファイルが必要です"
show_help
exit 1
fi
FILE1="$1"
FILE2="$2"
OUTPUT="${3:-output.txt}"
# ファイル存在確認
for file in "$FILE1" "$FILE2"; do
if [ ! -f "$file" ]; then
echo "エラー: ファイル '$file' が見つかりません"
exit 1
fi
done
# 結合実行
case "$MODE" in
"vertical")
cat "$FILE1" "$FILE2" > "$OUTPUT"
echo "縦結合完了: $OUTPUT"
;;
"horizontal")
if [ -n "$DELIMITER" ]; then
paste -d "$DELIMITER" "$FILE1" "$FILE2" > "$OUTPUT"
else
paste "$FILE1" "$FILE2" > "$OUTPUT"
fi
echo "横結合完了: $OUTPUT"
;;
"join")
# 一時ファイルでソート
sort "$FILE1" > "${FILE1}.sorted"
sort "$FILE2" > "${FILE2}.sorted"
if [ -n "$DELIMITER" ]; then
join -t "$DELIMITER" "${FILE1}.sorted" "${FILE2}.sorted" > "$OUTPUT"
else
join "${FILE1}.sorted" "${FILE2}.sorted" > "$OUTPUT"
fi
# 一時ファイル削除
rm -f "${FILE1}.sorted" "${FILE2}.sorted"
echo "キー結合完了: $OUTPUT"
;;
esac
# 結果表示
echo "結果ファイル: $OUTPUT"
echo "行数: $(wc -l < "$OUTPUT")"
まとめ
コマンド別の使い分け
cat(縦結合)
- 用途:ファイルを縦にくっつける(行を追加)
- 適用場面:ログファイルの統合、データの追記
- 基本構文:
cat file1.txt file2.txt > combined.txt
paste(横結合)
- 用途:ファイルを横にくっつける(行ごとに並列)
- 適用場面:CSVの列追加、データの項目追加
- 基本構文:
paste -d ',' file1.txt file2.txt
join(キーベース結合)
- 用途:共通キーでマッチした行を横に結合
- 適用場面:リレーショナルデータの結合
- 基本構文:
join file1.txt file2.txt
実用的な選択指針
データの性質で選ぶ:
- 時系列データ:cat で縦結合
- 項目追加:paste で横結合
- マスタ結合:join でキーベース結合
ファイル形式で選ぶ:
- ログファイル:主に cat
- CSVファイル:paste や join
- 構造化データ:join が最適
作業の目的で選ぶ:
- 単純な統合:cat
- データの拡張:paste
- データの関連付け:join
これらの知識があれば、ログ結合・CSVマージ・データ処理が格段に効率化します。
特に実際の業務では、これらのコマンドを組み合わせて使うことが多いので、基本をしっかり理解して応用に備えましょう!
コメント