Bashのブレース展開は、特定のパターンから複数の文字列を生成する非常に強力な仕組みです。これを知っているだけで、冗長なタイピングから解放されます。
目次
- 概要とメリット
- 基本的な構文
- プリアンブルとポストスクリプト
- 入れ子(ネスト)構造
- エスケープ
- 実用的な使い方の例
- 展開の順序と変数
- まとめ
概要とメリット
ブレース展開とは、Bashが持つ「7種類の展開」の1つです。波括弧 { } 内の要素をルールに基づいて展開し、複数の引数としてコマンドに渡します。
# Bash
echo {0..10}
# 出力
0 1 2 3 4 5 6 7 8 9 10
上記では、Bashが内部的に echo 0 1 2 3 4 5 6 7 8 9 10 というコマンドに変換してから実行しています。手動で10個の数字を打つ手間を省けるのが最大のメリットです。
基本的な構文
ブレース { } の中に、カンマ区切りのリストを入れるか、ドット2つの範囲を指定します。
1.カンマ区切り(リスト指定)
ブレース内に1つ以上のカンマで区切られた文字列を入れると、各文字列が展開されます。
# Bash
echo {apple,banana,cherry}
# 出力: apple banana cherry
⚠️ 注意: カンマの後にスペースを入れる(例: {a, b})と、Bashはブレース展開として認識せず、ただの文字列として扱います。スペース厳禁が鉄則です。
空の要素
カンマの前後に何も書かないと、空文字として扱われます。
# Bash
echo {,banana,cherry}
# 出力: banana cherry(先頭に空文字が生成される)
これ単体では使い道がなさそうですが、後述のプリアンブルと組み合わせると、ファイル操作で威力を発揮します。
2.ドット2つ(範囲指定)
{x..y}の形式で、整数やアルファベットの連続したシーケンスを生成します。
# Bash
echo {1..5}
# 出力: 1 2 3 4 5
# マイナスや降順も可能
echo {3..-3}
# 出力: 3 2 1 0 -1 -2 -3
# 小文字シーケンス
echo {a..e}
# 出力: a b c d e
# 大文字降順シーケンス
echo {E..A}
# 出力: E D C B A
ゼロ埋め
整数による範囲指定では0 を付けることで、桁数を揃えてくれます。
# Bash
echo {01..10}
# 実行結果: 01 02 03 04 05 06 07 08 09 10
不連続なシーケンス
{開始..終了..増分}の形式で、増分の数だけスキップできます。
$ Bash
echo {1..10..2}
# 出力: 1 3 5 7 9
# アルファベットでも可能
echo {a..z..5}
# 出力: a f k p u z
範囲指定で生成出来ないもの
- 日本語のようなマルチバイト文字のシーケンス:{あ..お}は「あ い う え お」とはならず、文字リテラルと解釈される。
- 大文字と小文字を含むシーケンス:{a..Z}はブレース展開されず文字リテラルと解釈される(ただし、後述の入れ子構造を使い
{{a..z},{A..Z}}とすれば可能)。 - 整数以外のシーケンス:小数点のシーケンス
{0.1..0.5}はブレース展開されず文字リテラルと解釈される(ただし後述のプレアンブルを使い0.{1..5}とすれば小数点シーケンス生成可能)。
プリアンブルとポストスクリプト
ブレースの直前(プリアンブル)や直後(ポストスクリプト)に文字列を置くと、展開されるすべての要素にその文字列が付与されます。
| 種類 | 例 | 結果 |
| プリアンブル | pre{A,B} | preA preB |
| ポストスクリプト | {A,B}post | Apost Bpost |
| 両方 | v{1,2}z | v1z v2z |
複数のブレースを並べると、左から順に組み合わされます。
# Bash
echo {a,b}{c,d}
# 出力
ac ad bc bd
上記の例は若干複雑ですが、以下の順番で展開されます。
- {a,b}が展開されてa bになる。
- a bにポストスクリプト{c,d}が後方接続され、a{c,d} b{c,d}となる。
- 各{c,d}が展開されc dとなり、プリアンブルaとbがそれぞれ前方接続され
ac ad bc bdとなる。
入れ子(ネスト)構造
ブレースの中にさらにブレースを入れることも可能です。この場合、内側から外側へと展開されます。
# Bash
echo {A,B{1..3}}
# : A B1 B2 B3
- B{1..3}がB1 B2 B3に展開される。
- {A,B1,B2,B3}が展開される。
大文字と小文字を両方含めたい場合などに便利です。
# Bash
echo {{a..c},{A..C}}
a b c A B C
エスケープ
ブレースそのものを文字として使いたい場合は、クォート(推奨)かバックスラッシュを使用します。
# Bash
echo '{1..10}'
# 出力: {1..10}
echo \{1..10\}
# 出力: {1..10}
実用的な使い方の例
ファイルの一括作成
project ディレクトリ内に src, bin, doc というフォルダを作成。
# Bash
mkdir -p project/{src,bin,doc}
バックアップの作成
プリアンブルと「空の要素」を組み合わせて同じファイルパスをタイプする手間を省略します。
# Bash
cp /path/to/data.txt{,.bak}
# cp /path/to/data.txt /path/to/data.txt.bak と同じ意味
ファイル名の変更
プリアンブルとポストスクリプトを組み合わせ、元のファイルパスや拡張子を書く手間が省けます。
$ Bash
mv /path/to/{oldname,newname}.txt
# これは mv /path/to/oldname.txt /path/to/newname.txt と解釈されます
複数ログファイルの一括検索
ログローテーションで作成された複数のログファイルを検索したい際、個別に指定する手間を省けます。
# Bash
grep '404' access.log{,.1} <(zcat access.log.{2..7}.gz)
*2~7日前の圧縮ログをBashのプロセス置換で展開しつつ、直近のログも同時に検索しています。
展開の順序と変数
ここは要注意ポイントです。ブレース展開は、変数展開($VAR)よりも先に実行されます。
$ Bash
END=10
echo {1..$END}
# 期待: 1 2 ... 10
# 実際: {1..10} ブレース展開はされず変数展開のみ
ブレースの中に変数を入れたい場合は、eval を使う必要があります(ただし、セキュリティ上の理由から慎重に扱うべきです)。
$ Bash
END=10
eval echo {1..$END}
# 出力: 1 2 3 4 5 6 7 8 9 10
また、${} という書き方はBashの「パラメータ展開」と誤認されるため、ブレース展開でドル記号を使いたい場合は注意しましょう。
# Bash
# echo $TERM $PATHとしたかったが誤り
echo ${TERM,PATH}
# 出力: xterm-256color
# ブレース展開はされず$TERMのみパラメータ展開される
まとめ
Bashのブレース展開は、コマンドライン操作を効率化する第一歩です。最初は慣れないかもしれませんが、cp や mkdir で少しずつ使ってみることで、日々の業務が驚くほどスムーズになります。
