mapfile
は標準入力(またはFD)から読み取った各レコードを配列に格納する Bash の組み込みコマンドです(別名:readarray
)。デリミタ(既定は改行)や読み取り件数、スキップ件数、コールバックなどを細かく制御できます。
実務では、コマンド出力やファイルの各行を安全に配列化して後段処理で扱うときに使います。
構文(Syntax)
# bash 4+
mapfile [-d DELIM] [-n COUNT] [-O ORIGIN] [-s COUNT] [-t] [-u FD] [-r]
[-C CALLBACK [-c QUANTUM]] ARRAY_NAME
# 同義コマンド
readarray … ARRAY_NAME
ARRAY_NAME
はインデックス配列名。各レコードがARRAY_NAME[0], [1], ...
に入ります。- 既定のデリミタは改行(
\n
)。-t
を付けると末尾のデリミタを除去します。
主なオプション一覧
オプション | 説明 | 使用例 |
---|---|---|
-t | 末尾のデリミタ(改行など)を取り除いて格納 | mapfile -t lines < file.txt |
-d DELIM | レコード区切り文字を指定(1文字)。NULは -d $'\0' | mapfile -d $'\0' -t items < list.nul |
-n COUNT | 最大 COUNT 件だけ読み込み | mapfile -n 5 -t top5 < file.txt |
-s COUNT | 先頭から COUNT 件を読み飛ばす | mapfile -s 1 -t body < file.csv |
-O ORIGIN | 配列の書き込み開始インデックス(追記に便利) | mapfile -O "${#arr[@]}" -t arr < more.txt |
-u FD | 指定FDから読む(既定は stdin ) | exec 3< file; mapfile -u 3 -t lines |
-r | バックスラッシュによるエスケープを無効化(そのまま読み込む) | mapfile -r -t raw < file |
-C CALLBACK | QUANTUM 行ごとに CALLBACK 関数を呼ぶ | mapfile -C progress -c 100 -t lines < big.txt |
-c QUANTUM | -C の呼び出し間隔(デフォルトは 5000) | -C cb -c 1000 |
実行例
ファイルの各行を配列に読み込む(基本)
説明:改行を除いた行配列を作ります。
コマンド
mapfile -t lines < /etc/hosts
printf '%s\n' "${lines[@]}" | head
出力例:/etc/hosts
の先頭行から表示。
プロセス置換でコマンド出力を配列化
説明:git ls-files
の結果を配列に格納します。
コマンド
mapfile -t tracked < <(git ls-files)
echo "計: ${#tracked[@]} 件"
先頭1行をヘッダとしてスキップして読む
説明:CSVの1行目(ヘッダ)を飛ばして読み込みます。
コマンド
mapfile -s 1 -t rows < data.csv
echo "データ行: ${#rows[@]}"
NUL区切り入力を安全に読む(ファイル名に改行があってもOK)
説明:find -print0
の出力を NUL 区切りで配列化。
コマンド
mapfile -d $'\0' -t files < <(find . -type f -print0)
printf '%q\n' "${files[@]}" | head
大きな入力で進捗表示(コールバック)
説明:100行ごとに進捗を表示するコールバックを使います。
コマンド
progress() { printf '\r... %s 行読み込み' "$1"; }
mapfile -C progress -c 100 -t big < biglist.txt
echo -e "\n完了: ${#big[@]} 行"
エラー例:存在しないFDを指定
説明:未オープンのFDを -u
に渡すと失敗します。
コマンド
mapfile -u 9 -t lines
echo $?
出力例(例)
bash: mapfile: -u: invalid file descriptor specification
1
関連コマンド
read
:1レコードずつ読み込む基本コマンド(-r
,-d
等)。printf
:配列内容の整形出力に。xargs -0
/find -print0
:NUL 区切りでの受け渡し。while IFS= read -r line; do ...; done
:逐次処理の定番パターン。
備考
- Bash限定:
mapfile/readarray
は Bash専用です(POSIXsh
やdash
にはありません)。 - デリミタ:
-d
は1文字のみ有効。NUL は-d $'\0'
を使用してください。-t
を併用すると末尾デリミタを落とせます。 - 改行・バックスラッシュ:改行を保持したい場合は
-t
を付けないこと。バックスラッシュをそのまま残したい場合は-r
を付けます。 - 巨大入力:配列に全読み込みするためメモリを消費します。行ごと処理で十分な場合は
while read
ループの方が安全です。 - コールバック:
-C name -c N
のコールバックには「読込済み行数(1始まり)」が$1
で渡されます。副作用の強い処理は避け、軽量に保つのが無難です。
参考
- Bash Reference Manual(Bourne Shell Builtins /
readarray
(mapfile
))
https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html#index-readarray bash(1)
manページ(組み込みコマンド・mapfile
)
https://man7.org/linux/man-pages/man1/bash.1.htmlhelp mapfile
(ローカルの Bash で詳細ヘルプ)
コメント