Brace yourself
This is part of Underappreciated Bash idioms, which see.
Though not entirely unknown, brace expansion is most commonly used interactively, usually for things such as the creation of multiple files or directories.
Yet there's more to them than that.
Directories and files
This produces five empty files:
touch file{1..5}
And this creates 36 subdirectories — one for each month for each year from 2042 to 2044:
mkdir -p ~/Documents/long/path/to/something/dates/204{2..4}/{01..12}
Try this to see how the expansion works:
echo dates/204{2..4}/{01..12}
Now, did you know you can do the opposite?
Generating braces
In the terminal, go to some empty directory and create these 12 empty files:
touch {foo,bar}-{a,b,c{1,2,3{g,h}}}
List them:
ls
Ok, now you want to copy the foo ones somewhere.
You type cp foo TAB TAB TAB — there, you see the completions.
But they're not available. You want to make them available.
You type cp foo ESC * — there, all the foo files listed after the command.
You cancel that with Ctrl-C.
You type cp foo Alt-{ — there, same thing, but as braces.
You can Alt-{ while in any directory to complete-into-braces.
Numbers and combinatorics
You can use brace expansion just for generating strings.
Here're multiples of 3 between 0 and 20, followed by multiples of 5 between 50 and 27:
echo {0..20..3} " AND " {50..27..-5}
0 3 6 9 12 15 18 AND 50 45 40 35 30
Alphabet letters — just the odd ones:
echo {a..z..2}
a c e g i k m o q s u w y
All combinations of these four letters and two numbers:
echo {b,a,s,h}{4,2}
b4 b2 a4 a2 s4 s2 h4 h2
Four coin tosses:
echo {H,T}{H,T}{H,T}{H,T}
HHHH HHHT HHTH HHTT HTHH HTHT HTTH HTTT THHH THHT THTH THTT TTHH TTHT TTTH TTTT
Two dice throws:
echo {1..6}{1..6}
11 12 13 14 15 16 21 22 23 24 25 26 31 32 33 34 35 36 41 42 43 44 45 46 51 52 53 54 55 56 61 62 63 64 65 66
And a whole deck of cards:
echo {♠,♥,♦,♣}{A,{2..10},J,Q,K} | xargs -n 13 | sed -E 's/([♠♥♦♣])([^ ]+)/\2\1/g'
A♠ 2♠ 3♠ 4♠ 5♠ 6♠ 7♠ 8♠ 9♠ 10♠ J♠ Q♠ K♠ A♥ 2♥ 3♥ 4♥ 5♥ 6♥ 7♥ 8♥ 9♥ 10♥ J♥ Q♥ K♥ A♦ 2♦ 3♦ 4♦ 5♦ 6♦ 7♦ 8♦ 9♦ 10♦ J♦ Q♦ K♦ A♣ 2♣ 3♣ 4♣ 5♣ 6♣ 7♣ 8♣ 9♣ 10♣ J♣ Q♣ K♣
Repeating
Sometimes you need to repeat things.
To get 4 foo, use 4−1 = 3 commas:
echo foo{,,,}
foo foo foo foo
To get 15, use 15−1 = 14 commas:
echo foo{,,,,,,,,,,,,,,}
But 5×3 = 15, so you can use (5−1)×(3−1) instead — same result:
echo foo{,,,,}{,,}
foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo
Splitting
When the output comes in one line and you want to split it, you can use sed:
echo foo{,,,,}{,,} | sed -E 's/.{20}/&\n/g'
or fold:
echo foo{,,,,}{,,} | fold -w20
but these two do it by counting characters ("foo " × 5 = 20), whereas xargs:
echo foo{,,,,}{,,} | xargs -n5
counts words.
Any of these last three produce this:
foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo
Grouping
When the input comes in many lines, you might want to do the opposite: group it.
Then paste is handy:
seq -w 42 | paste -d' ' - - - - - -
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
But what if it's 84 and you wanted four lines of 21?
Then you need 21 dashes:
seq -w 84 | paste -d' ' - - - - - - - - - - - - - - - - - - - - -
which you can also produce with one dash plus 20 commas inside braces:
seq -w 84 | paste -d' ' -{,,,,,,,,,,,,,,,,,,,,}
which, as every Emacs user knows, can be produced with C-2 C-0 , — keys that'll also work in your terminal.
But 7×3 = 21, so this would also do it:
seq -w 84 | paste -d' ' -{,,,,,,}{,,}
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
Trees?
Finally, as I mentioned years ago, although Bash ostensibly doesn't have tree-like data types, nested braces are isomorphic to tree structures.
This tree's root-to-leave paths:
a ├─bc │ ├─e │ └─f └─bd ├─e └─f
can be listed with:
echo a%{bc,bd}%{e,f} | sed 'y/ %/\n /'
a bc e a bc f a bd e a bd f
and this one:
a ├─bc │ ├─e │ └─f └─bd ├─f ├─g └─h
with this:
echo a%{bc%{e,f},bd%{f,g,h}} | sed 'y/ %/\n /'
a bc e a bc f a bd f a bd g a bd h
Remember, this is Bash.
Don't expect compiler warnings.
These are small miracles made of string.
Want to handle complex lists and trees without having nightmares about braces?
Try Lisp.
📆 2025-11-10