The Borne Again Shell (BASH) has a lot of great features that it borrows from other shells and even from some programming languages. It was created in the late 1980s in a response to a lacking in the current available shells on Berkley Distributions (BSD), and the predecessor to Linux, GNU. BASH features numerous in-built features such as in-line scripting capabilities like brace expansion, which we are going to examine today.

What is Brace Expansion and Why Do I Need to Know It?

Brace expansions are tools that permit the generation of a range of strings to be used on the command line. They follow the grammar of ‘Prefix {Range} Post-fix’. Both pre- and post-fixes are optional as the range can act alone. Using Bash's brace expansions you can become more efficient on the Linux command line.

The best way to introduce you to brace expansion is with a scenario. Many system administrators work with files and folders on the command line daily. They may need to create a set of folders to organize your files, logs, outputs, or projects into discrete folders. The hang up is the burdensome repetition of the folder creation loop.

Here is an example of how you can create 9 sequentially named folders using bash history and a few additional keystrokes:

example of how bash brace expansion can save you time on the command line

Bash Brace Expansion Examples

Using Sequence Expressions

Using Bash brace expansions you can create the above folders a lot more efficiently using Bash brace expansion.

[mcherisi@putor ~]$ mkdir ~/hello/{1..9}
[mcherisi@putor ~]$ ls -l ~/hello/
total 36
drwxr-xr-x. 2 mcherisi mcherisi 4096 Jan 21 15:23 1
drwxr-xr-x. 2 mcherisi mcherisi 4096 Jan 21 15:23 2
drwxr-xr-x. 2 mcherisi mcherisi 4096 Jan 21 15:23 3
...OUTPUT TRUNCATED...

As you can see, this creates 9 directories named 1 through 9. That is much easier than the manual file creation process shown in the first animation.

There are more useful cases in which you might use brace expansion, for instance, creating folders for log files or for data dumps. This example also brings to light nested bracing.

[mcherisi@putor ~]$ mkdir -p ~/logs/{January/{1..31},February/{1..28},March/{1..31}}
[mcherisi@putor ~]$ 
[mcherisi@putor ~]$ ls -l ~/logs/
total 12
drwxr-xr-x. 30 mcherisi mcherisi 4096 Jan 21 15:27 February
drwxr-xr-x. 33 mcherisi mcherisi 4096 Jan 21 15:27 January
drwxr-xr-x. 33 mcherisi mcherisi 4096 Jan 21 15:27 March
[mcherisi@putor ~]$ 
[mcherisi@putor ~]$ ls -l ~/logs/January/
total 124
drwxr-xr-x. 2 mcherisi mcherisi 4096 Jan 21 15:27 1
drwxr-xr-x. 2 mcherisi mcherisi 4096 Jan 21 15:27 10
drwxr-xr-x. 2 mcherisi mcherisi 4096 Jan 21 15:27 11
...OUTPUT TRUNCATED...

Let's break this example down so we can understand what is happening.

The command mkdir creates directories, the -p switch created parent directories if they do not already exist.

~/logs/{January/{1..31},February/{1..28},March/{1..31}} enters the directory called "logs" and creates the folders January with the sub-folders 1 through 31, February, with the sub-folders 1 through 28, and March, with the sub folders 1 through 31.

Note the usage of the two-period ellipsis in the preceding example, this short hand saves you from the typing out mkdir /logs/January/1, mkdir /logs/January/2, and so on.

Let's take a look at another example.

[mcherisi@putor ~]$ touch ~/logs/January/{1..31}/log.daily
[mcherisi@putor ~]$ 
[mcherisi@putor ~]$ ls ~/logs/January/6/
log.daily

In this example, we use brace expansion to create a file named log.daily in each of the sub-directories in January.

Brace Expansion permits steps by any sequentially occurring data, such as letters and numbers. The expansions can increment in either the positive {1..5} or the negative {5..1} directions, and can include negative numbers (ex. {0..-5}). Letters are also accepted as in {a..z} or {z..a}.

Using Non-sequential Expressions

We have now covered using brace expansion for sequential tasks (creating folders 1 to 9). However, it can also be used for non-sequential items as well.

Let's pretend you had a Fruits directory and you wanted to create 5 folders named after your favorite fruits. You could just run the mkdir command multiple times like so:

[mcherisi@putor Fruit]$ mkdir bananas
[mcherisi@putor Fruit]$ mkdir apples
[mcherisi@putor Fruit]$ mkdir oranges
[mcherisi@putor Fruit]$ mkdir peaches
[mcherisi@putor Fruit]$ mkdir kiwis

To be more efficient you can use brace expansion to generate all the files in one command.

[mcherisi@putor Fruit]$ mkdir {bananas,apples,oranges,peaches, kiwis}

This is especially handy when you need to work with files that have long paths.

How Does Brace Expansion Work?

Brace expansions function as an in-line loop. In programming, a loop is a construct that cycles through a repetitive set of instructions until it satisfies all events. In the preceding example for creating log files in the folders, the expansion of January/{1..31}/log.daily is processed as such:

  1. Go to path ~/logs/January/
  2. <begin loop> Enter folder ‘1’
  3. Does the file log.daily exist? If yes, do nothing, if no create it.
  4. Exit folder ‘1’ <continue/end loop>
  5. Enter folder ‘2’

This process will repeat until a log.daily exists in every one of the January 1 through 31 folders.

Conclusion

Brace expansions are not limited to simple letters and numbers, you can use words as well, but I am using simple conventions for ease of demonstration. Implemented correctly, it can make you more efficient on the command line, your shell scripting more concise and easier to read, and it’ll save you time and keystrokes.