Last updated on March 29, 2021 by Dan Nanni
When you are writing a bash script, there are situations where you need to generate a sequence of numbers or strings. One common use of such sequence data is for loop iteration. When you iterate over a range of numbers, the range may be defined in many different ways (e.g., [0, 1, 2,..., 99, 100], [50, 55, 60,..., 75, 80], [10, 9, 8,..., 1, 0], etc). Loop iteration may not be just over a range of numbers. You may need to iterate over a sequence of strings with particular patterns (e.g., incrementing filenames; img001.jpg, img002.jpg, img003.jpg). For this type of loop control, you need to be able to generate a sequence of numbers and/or strings flexibly.
While you can use a dedicated tool like seq
to generate a range of numbers, it is really not necessary to add such external dependency in your bash script when bash itself provides a powerful built-in range function called brace expansion. In this tutorial, let's find out how to generate a sequence of data in bash using brace expansion and what are useful brace expansion examples.
Bash's built-in range function is realized by so-called brace expansion. In a nutshell, brace expansion allows you to generate a sequence of strings based on supplied string and numeric input data. The syntax of brace expansion is the following.
{<string1>,<string2>,...,<stringN>} {<start-number>..<end-number>} {<start-number>..<end-number>..<increment>} <prefix-string>{......} {......}<suffix-string> <prefix-string>{......}<suffix-string>
All these sequence expressions are iterable, meaning you can use them for while/for loops. In the rest of the tutorial, let's go over each of these expressions to clarify their use cases.
The first use case of brace expansion is a simple string list, which is a comma-separated list of string literals within the braces. Here we are not generating a sequence of data, but simply list a pre-defined sequence of string data.
{<string1>,<string2>,...,<stringN>}
You can use this brace expansion to iterate over the string list as follows.
for fruit in {apple,orange,lemon}; do echo $fruit done
apple orange lemon
This expression is also useful to invoke a particular command multiple times with different parameters.
For example, you can create multiple subdirectories in one shot with:
$ mkdir -p /home/xmodulo/users/{dan,john,alex,michael,emma}
To create multiple empty files:
$ touch /tmp/{1,2,3,4}.log
The most common use case of brace expansion is to define a range of numbers for loop iteration. For that, you can use the following expressions, where you specify the start/end of the range, as well as an optional increment value.
{<start-number>..<end-number>} {<start-number>..<end-number>..<increment>}
To define a sequence of integers between 10 and 20:
echo {10..20} 10 11 12 13 14 15 16 17 18 19 20
You can easily integrate this brace expansion in a loop:
for num in {10..20}; do echo $num done
To generate a sequence of numbers with an increment of 2 between 0 and 20:
echo {0..20..2} 0 2 4 6 8 10 12 14 16 18 20
You can generate a sequence of decrementing numbers as well:
echo {20..10} 20 19 18 17 16 15 14 13 12 11 10
echo {20..10..-2} 20 18 16 14 12 10
You can also pad the numbers with leading zeros, in case you need to use the same number of digits. For example:
echo {00..20..2} 00 02 04 06 08 10 12 14 16 18 20
Brace expansion can be used to generate not just a sequence of numbers, but also a sequence of characters.
{<start-character>..<end-character>}
To generate a sequence of alphabet characters between 'd' and 'p':
echo {d..p} d e f g h i j k l m n o p
You can generate a sequence of upper-case alphabets as well.
for char1 in {A..B}; do for char2 in {A..B}; do echo "${char1}${char2}" done done
AA AB BA BB
It's possible to add a prefix and/or a suffix to a given brace expression as follows.
<prefix-string>{......} {......}<suffix-string> <prefix-string>{......}<suffix-string>
Using this feature, you can easily generate a list of sequentially numbered filenames:
# create incrementing filenames for filename in img_{00..5}.jpg; do echo $filename done
img_00.jpg img_01.jpg img_02.jpg img_03.jpg img_04.jpg img_05.jpg
Finally, it's possible to combine multiple brace expansions, in which case the combined expressions will generate all possible combinations of sequence data produced by each expression.
For example, we have the following script that prints all possible combinations of two-character alphabet strings using double-loop iteration.
for char1 in {A..Z}; do for char2 in {A..Z}; do echo "${char1}${char2}" done done
By combining two brace expansions, the following single loop can produce the same output as above.
for str in {A..Z}{A..Z}; do echo $str done
In this tutorial, I described a bash's built-in mechanism called brace expansion, which allows you to easily generate a sequence of arbitrary strings in a single command line. Brace expansion is useful not just for a bash script, but also in your command line environment (e.g., when you need to run the same command multiple times with different arguments). If you know any useful brace expansion tips and use cases, feel free to share it in the comment.
bash
shell scripting tutorials provided by Xmodulo.This website is made possible by minimal ads and your gracious donation via PayPal or credit card
Please note that this article is published by Xmodulo.com under a Creative Commons Attribution-ShareAlike 3.0 Unported License. If you would like to use the whole or any part of this article, you need to cite this web page at Xmodulo.com as the original source.
Xmodulo © 2021 ‒ About ‒ Write for Us ‒ Feed ‒ Powered by DigitalOcean