Bash/Klammerexpansion

Aus Foxwiki

topic kurze Beschreibung

Bash brace expansion is used to generate stings at the command line or in a shell script.

Beschreibung

Installation

Anwendungen

Syntax

Optionen

Parameter

Umgebungsvariablen

Exit-Status

Konfiguration

Dateien

Sicherheit

Dokumentation

RFC

Man-Pages

Info-Pages

Siehe auch

Links

Projekt-Homepage

Weblinks

  1. Introduction to expansion and substitution

Einzelnachweise

Testfragen

Testfrage 1

Antwort1

Testfrage 2

Antwort2

Testfrage 3

Antwort3

Testfrage 4

Antwort4

Testfrage 5

Antwort5

TMP

Mit Hilfe der Klammererweiterung lassen sich beliebige Zeichenketten generieren.

Brace expansion

Im einfachsten Fall verwendet man eine Präfix-Zeichenkette, gefolgt von beliebig vielen, mit geschweiften Klammern umschlossenen und durch Kommas getrennten Zeichen(ketten), wiederum gefolgt von einer optionalen Postfix-Zeichenkette.

Das Ergebnis sind nun Zeichenketten der Art "PräfixZeichenkette_1_Postfix", "PräfixZeichenkette_2_Postfix",..., "PräfixZeichenkette_n_Postfix".

$ echo Beispiel{_1_,_2_,_3_}
Beispiel_1_ Beispiel_2_ Beispiel_3_

Präfix und Postfix können ihrerseits wiederum Klammererweiterungen sein und Klammererweiterungen können verschachtelt werden, sodass sich z.B. mit nur einem Befehl eine ganze Verzeichnishierarchie erzeugen lässt:

$ mkdir -p bsp/{ucb/{ex,edit},lib/{bla,foo}}
$ du bsp | cut -b 3-
bsp/ucb/ex
bsp/ucb/edit
bsp/ucb
bsp/lib/bla
bsp/lib/foo
bsp/lib
bsp

Der Klammer-Mechanismus der eine große Menge an Zeichenketten erzeugen kann.

  • Muster für die Klammerexpansion (brace-expanded) haben eine optionale PREAMBLE, gefolgt von einer kommaseparierten Liste von Zeichenketten zwischen einem Paar von Klammern gefolgt von einem optionalem POSTSCRIPT.
  • Die PREAMBLE wir jeder Zeichenkette vorangestellt, dass die Klammern enthalten, dass POSTSCRIPT wird an jede Ergebniszeichenkette abgehangen.
  • Die Klammererweiterung kann auch verschachtelt werden.
  • Das Ergebnis wird nicht sortiert, die links-zu-rechts-Ordnung bleibt erhalten.
$ echo sp{el,il,al}l
spell spill spall

Die brace expansion wird vor allen anderen Expansionen ausgeführt und alle Zeichen, die für andere Expansionen eine besondere Bedeutung haben bleiben erhalten; es ist eine reine Textoperation.

  • Die Bash führt keine syntaktische Interpretationen durch.
  • Um Konflikte mit der parameter expansion zu vermeiden, werden Zeichenketten die mit "${" beginnen, nicht als brace expansion verstanden.
  • Eine korrekt formulierte brace expansion muss eine unmaskierte öffnende und schließende Klammer besitzen und mindestens ein unmaskiertes Komma enthalten.
  • Fehlerhaft formulierte brace expansion werden von der Bash nicht korrigiert.

Backup erstellen

$ cp -p /etc/apache2/plesk.conf.d/roundcube.conf{,.conf_back}

Brace expansion

Ähnlich wie die Expansion von Dateinamen ist die Expansion von geschweiften Klammern eine kompakte Methode, um mehrere ähnliche Argumente darzustellen.

Die folgenden vier Befehle sind gleichwertig:

$ ls file1.txt file2.txt file3.txt file4.txt file5.txt
$ ls file{1,2,3,4,5}.txt
$ ls file{1..5..1}.txt
$ file{1..5}.txt
  • Der erste Befehl listet jedes Argument explizit auf.
  • Die anderen drei Befehle verwenden alle Klammererweiterungen, um die Argumente knapper auszudrücken:
  • beim zweiten Befehl werden alle Möglichkeiten von 1 bis 5 angegeben, getrennt durch Kommas
  • beim dritten Befehl wird eine numerische Folge angegeben ("von 1 bis 5, aufsteigend um 1")
  • der vierte Befehl ist derselbe wie der dritte, lässt aber die ..1 implizit.

Wir können die Dateien auch in der umgekehrten Reihenfolge auflisten:

$ ls file5.txt file4.txt file3.txt file2.txt file1.txt
$ ls file{5,4,3,2,1}.txt
$ ls file{5..1..-1}.txt
$ ls file{5..1}.txt

wobei die Standard-Inkrementgröße -1 ist, wenn der Endpunkt der Sequenz kleiner ist als der Startpunkt.

Da in der Bash das erste Wort eines Befehls das Programm ist, das ausgeführt wird, könnten wir den Befehl auch so schreiben:

$ {ls,file{1..5}.txt}

aber das ist natürlich der Lesbarkeit nicht förderlich.

Dasselbe kann übrigens auch mit der Expansion von Dateinamen gemacht werden.

Die Expansion von geschweiften Klammern kann wie die Expansion von Dateinamen durch jeden der Anführungszeichen-Mechanismen deaktiviert werden; '{', "{" oder \{ erzeugt eine tatsächliche geschweifte Klammer.

Beispiel

# root@debian ~ # chown -Rc dirkwagner.dirkwagner /media/daten/{tools,kurse,ebooks}

TMP

Bash Brace Expansion

The syntax for brace expansion consists of either a sequence specification or a comma separated list of items inside curly braces "{}". A sequence consists of a starting and ending item separated by two periods "..".

Some examples and what they expand to:

{aa,bb,cc,dd}  => aa bb cc dd
{0..12}        => 0 1 2 3 4 5 6 7 8 9 10 11 12
{3..-2}        => 3 2 1 0 -1 -2
{a..g}         => a b c d e f g
{g..a}         => g f e d c b a

If the brace expansion has a prefix or suffix string then those strings are included in the expansion:

a{0..3}b       => a0b a1b a2b a3b

Brace expansions can be nested:

{a,b{1..3},c}  => a b1 b2 b3 c

Counted loops in bash can be implemented a number of ways without brace expansion:

# Three expression for loop:
for (( i = 0; i < 20; i++ ))
do
    echo $i
done
# While loop:
i=0
while $i -lt 20 
do
    echo $i
    let i++
done
# For loop using seq:
for i in $(seq 0 19)
do
    echo $i
done

A counted for loop using bash sequences requires the least amount of typing:

for i in {0..19}
do
    echo $i
done

But beyond counted for loops, brace expansion is the only way to create a loop with non-numeric "indexes":

for i in {a..z}
do
    echo $i
done

Brace expansion can also be useful when passing multiple long pathnames to a command. Instead of typing:

# rm /a/long/path/foo /a/long/path/bar

You can simply type:

# rm /a/long/path/{foo,bar}

Brace expansion is enabled via the "set -B" command and the "-B" command line option to the shell and disabled via "set +B" and "+B" on the command line.

Q: https://www.linuxjournal.com/content/bash-brace-expansion

Bash Brace Expansion In Linux with Examples

Brасe exраnsiоn is а wаy by whiсh аrbitrаry strings саn be generаted frоm the terminаl оr by using any bаsh sсriрt, it allows you to create multiple modified command-line arguments out of a single argument. The syntаx fоr brасe exраnsiоn соnsists оf either a sequenсe sрeсifiсаtiоn оr а cоmmа seраrаted list оf dаtа inside сurly brасes “{}”.  The раttern shоuld nоt cоntаin embedded whitesрасe. There are two optional parts to Brace expansion — Preamble and Postscript. The Preamble is prefixed to each string contained within the braces, and the Postscript is then appended to each resulting string, expanding left to right.

Method 1: Using Comma-separated lists

echo {geeks,for,geeks}
echo {"hello","world"}

Method 2: Using Ranges, Different types of ranges can be used, like numeric, alphabetic, or both. A sequence consists of a starting and ending term separated by 2 periods “..” inside curly braces “{}”.

echo {A..D}
echo {3..8}
echo {A..C}{1..2}

Method 3: Using Preamble, Patterns to be brace expanded may contain a leading term called a preamble. The brace expression may contain either a comma-separated list or a range.

echo gfg{1..4}
echo gfg{1,5,9}

Method 4: Using Postscript, Like Preamble, it can also have an ending portion known as Postscript.

echo {1..3}gfg
echo {1,5,9}gfg

Bash Expansion can be nested.

echo {a,b{1..3},c}

Bash Expansion can be used with other commands also, like, we can make multiple folders with one command using Brace expansion with mkdir command.

Q: https://www.geeksforgeeks.org/bash-brace-expansion-in-linux-with-examples/

Bash brace expansion

Bash uses brace expansion to generate a sequence of strings from the terminal or by using any bash script. A sequence of expressions or comma-separated list of data with curly brackets is used to define brace expansion. Two optional parts of brace expansion are preamble and postscript. The preamble is used to add text at the front of each generated string and postscript is used to append text at the end of the generated string by using brace expansion. How the user can create different types of random strings using bash brace expansion is explained in this tutorial by using various examples.

Syntax:# String List

{String1, String2,... ,StringN }# Range List
{<start> . . <end>}# Preamble and postscript
<preamble>{ string or range }{ string or range }<postscript><preamble{ string or range }<postscript>

The above syntax shows that you can use brace expansion without preamble and postscript or with preamble or with postscript or with both. Different uses of brace expansions are shown in the next part of this tutorial by using various examples.

Example-1: Using comma-separated lists

The following command shows the use of brace expansion with comma-separated list only. You have to remember one thing while defining the list. That is, list items must be separated by comma only and don’t add any space between the items, otherwise brace expansion will not work. Here, the first command will display the list items with space. Two lists are used in the second command and the output will generate by combining each items of each list.

$ echo {PHP,Javascript,JQuery}$ echo {"I like ","Learn "}{"PHP","Programming"}

Output:

The following output will appear after running the script. In the second command, there are two items in each list and there are two lists. So, the second command will print (2X2=4), four text as output.

Datei:Bild6.png

Example-2: Using Ranges

Different types of ranges can be used in brace expansion to generate the list of data. The uses of four types of ranges are shown in this example. The first range will create a list of numeric data, starting from 50 to 60. The second range will generate a list of alphabetic characters, starting from A to F. The third range will generate a list of number, starting from 1 to 5 with leading zero. The forth range will generate a list of alpha-numeric data by combining A to C and 1 to 3.

$ echo {50..60}$ echo {A..E}$ echo {01..05}$ echo {A..C}{1..3}

Output:

The following output will appear after running the above commands. In the last command, the first brace expansion contains three items and the second brace expansion contains three items. So, the total items in the output will be, 3X3 = 9.

Datei:Bild7.png

Example-3: Using preamble

This example shows the use of preamble in brace expansion. The first command will add the string, “Hi “ with each item of the list and generate the output. The second command will add ‘b’ with each item of the list. This type of task is beneficial if you want to add a common text or character at the front of each list item.

$ echo "Hi "{John, Mohammed, Lisa}$ echo b{all, ell, oat, eef}

Output

The following output will appear after running the commands.

Datei:Bild8.png

Example-4: Using postscript

This example shows the use of postscript in brace expansion. The text, “ is a programmer” will add at the end of each list item in the first command. The word, “ball” will add with each item of the list in the second command. If the last part of each item of the list are same then it is better to create the list by brace expansion with postscript.

$ echo {John,Mohammed,Lisa}" is a programmer."$ echo {basket,foot,volley}ball

Output:

The following output will appear after running the commands.

Datei:Bild9.png

Example-5: Using both preamble and postscript

When the first part and last part of each item of the list are same then it better to create the list by using brace expansion with preamble and postscript. Here, the first command will add “Hi “, at the beginning of each list item and “ welcome to LinuxHint.“, at the end of the each list item. The second command will generate an alpha-numeric list by adding “*****” at the front and “.*****” at the end of the list item. According to the range, the first item is Q01 and the last item is Q05.

$ echo "Hi, "{John,Mohammed,Lisa}" welcome to LinuxHint."$ echo "*****Q"{01..05}".*****"

Output:

The following output will appear after running the commands.

Datei:Bild10.png

Example-6: Creating sequence of directory and file

`echo` command is used in all previous examples of this tutorial. But you can use brace expansion with other commands also. How you can create multiple files or folders in a single command by using brace expansion is shown in this tutorial. The following command will create three folders, Design, Programming and Framework, by using `mkdir` command and brace expansion.

$ mkdir {Design,Programming,Framework}$ ls

Output:

The following output will appear after running the commands.

Datei:Bild11.png

You can also create sequential multiple files by using touch and brace expansion with preamble and postscript. In this example, `touch` command is used to create multiple files. “ps” is used as preamble, “.py” is used as postscript and 1..3 range is used to create the sequential file names. The second command, ‘ls’ will show the files are created or not.

$ touch “ps”{1..3}”.py”
$ ls

Output

The following output will appear after running the commands. Here, three files will be created. These are ps1.py, ps2.py and ps3.py.

Datei:Bild12.png

Conclusion

Brace expansion is very useful for generating a list of sequential data or running any command on sequence of data. Some common uses of brace expansion are shown in this tutorial. Hope, the reader will be able to use brace expansion properly after practicing the examples of this tutorial.

Q: https://linuxhint.com/bash_brace_expansion/

Brace expansion

{string1,string2,...,stringN}
{<START>..<END>}
{<START>..<END>..<INCR>} (Bash 4)
<PREFIX>{........}
{........}<SUFFIX>
<PREFIX>{........}<SUFFIX>

Brace expansion is used to generate arbitrary strings. The specified strings are used to generate all possible combinations with the optional surrounding prefixes and suffixes.

Usually it's used to generate mass-arguments for a command, that follow a specific naming-scheme.

":!:"

It is the very first step in expansion-handling, it's important to understand that. When you use

echo {a,b}$PATH

then the brace expansion does not expand the variable - this is done in a later step. Brace expansion just makes it being:

echo a$PATH b$PATH

Another common pitfall is to assume that a range like {1..200} can be expressed with variables using {$a..$b}. Due to what I described above, it simply is not possible, because it's the very first step in doing expansions. A possible way to achieve this, if you really can't handle this in another way, is using the eval command, which basically evaluates a commandline twice:

eval echo {$a..$b}

For instance, when embedded inside a for loop :

for i in $(eval echo {$a..$b})

This requires that the entire command be properly escaped to avoid unexpected expansions. If the sequence expansion is to be assigned to an array, another method is possible using declaration commands:

declare -a 'pics=(img{'"$a..$b"'}.png)'; mv "${pics[@]}" ../imgs

This is significantly safer, but one must still be careful to control the values of $a and $b. Both the exact quoting, and explicitly including "-a" are important.

The brace expansion is present in two basic forms, string lists and ranges.

It can be switched on and off under runtime by using the set builtin and the option -B and +B or the long option braceexpand. If brace expansion is enabled, the stringlist in SHELLOPTS contains braceexpand.

String lists

{string1,string2,...,stringN}

Without the optional prefix and suffix strings, the result is just a space-separated list of the given strings:

$ echo {I,want,my,money,back}
I want my money back

With prefix or suffix strings, the result is a space-separated list of all possible combinations of prefix or suffix specified strings:

$ echo _{I,want,my,money,back}
_I _want _my _money _back
$ echo {I,want,my,money,back}_
I_ want_ my_ money_ back_
$ echo _{I,want,my,money,back}-
_I- _want- _my- _money- _back-

The brace expansion is only performed, if the given string list is really a list of strings, i.e., if there is a minimum of one "," (comma)! Something like {money} doesn't expand to something special, it's really only the text "{money}".

Ranges

{<START>..<END>}

Brace expansion using ranges is written giving the startpoint and the endpoint of the range. This is a "sequence expression". The sequences can be of two types * integers (optionally zero padded, optionally with a given increment)

  • characters
$ echo {5..12}
5 6 7 8 9 10 11 12
$ echo {c..k}
c d e f g h i j k

When you mix these both types, brace expansion is not performed:

$ echo {5..k}
{5..k}

When you zero pad one of the numbers (or both) in a range, then the generated range is zero padded, too:

$ echo {01..10}
01 02 03 04 05 06 07 08 09 10

There's a chapter of Bash 4 brace expansion changes at the end of this article.

Similar to the expansion using stringlists, you can add prefix and suffix strings:

$ echo 1.{0..9}
1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9
$ echo ---{A..E}---
---A--- ---B--- ---C--- ---D--- ---E---

Combining and nesting

When you combine more brace expansions, you effectively use a brace expansion as prefix or suffix for another one. Let's generate all possible combinations of uppercase letters and digits:

$ echo {A..Z}{0..9}
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 C0 C1 C2 C3 C4 C5 C6
C7 C8 C9 D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 F0 F1 F2 F3
F4 F5 F6 F7 F8 F9 G0 G1 G2 G3 G4 G5 G6 G7 G8 G9 H0 H1 H2 H3 H4 H5 H6 H7 H8 H9 I0
I1 I2 I3 I4 I5 I6 I7 I8 I9 J0 J1 J2 J3 J4 J5 J6 J7 J8 J9 K0 K1 K2 K3 K4 K5 K6 K7
K8 K9 L0 L1 L2 L3 L4 L5 L6 L7 L8 L9 M0 M1 M2 M3 M4 M5 M6 M7 M8 M9 N0 N1 N2 N3 N4
N5 N6 N7 N8 N9 O0 O1 O2 O3 O4 O5 O6 O7 O8 O9 P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 Q0 Q1
Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 S0 S1 S2 S3 S4 S5 S6 S7 S8
S9 T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 U0 U1 U2 U3 U4 U5 U6 U7 U8 U9 V0 V1 V2 V3 V4 V5
V6 V7 V8 V9 W0 W1 W2 W3 W4 W5 W6 W7 W8 W9 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 Y0 Y1 Y2
Y3 Y4 Y5 Y6 Y7 Y8 Y9 Z0 Z1 Z2 Z3 Z4 Z5 Z6 Z7 Z8 Z9

Hey.. that saves you writing 260 strings!

Brace expansions can be nested, but too much of it usually makes you losing overview a bit ";-)"

Here's a sample to generate the alphabet, first the uppercase letters, then the lowercase ones:

$ echo {{A..Z},{a..z}}
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z

Common use and examples

Massdownload from the Web

In this example, wget is used to download documentation that is split over several numbered webpages.

wget won't see your braces. It will see 6 different URLs to download.

wget http://docs.example.com/documentation/slides_part{1,2,3,4,5,6}.html

It's possible, and even easier, to do that with a sequence:

wget http://docs.example.com/documentation/slides_part{1..6}.html

Generate a subdirectory structure

Your life is hard? Let's ease it a bit - that's what shells are here for.

mkdir /home/bash/test/{foo,bar,baz,cat,dog}

Generate numbers with a prefix 001 002 ...

Using a prefix:

for i in 0{1..9} 10; do printf "%s\n" "$i";done

If you need to create words with the number embedded, you can use nested brace:

printf "%s\n" img{00{1..9},0{10..99},{100..999}}.png* Formatting the numbers with printf:
echo $(printf "img%02d.png " {1..99})

See the text below for a new Bash 4 method.

Repeating arguments or words

somecommand -v -v -v -v -v

Can be written as

somecommand -v{,,,,}

…which is a kind of a hack, but hey, it works.

More fun

The most optimal possible brace expansion to expand n arguments of course consists of n's prime factors. We can use the "factor" program bundled with GNU coreutils to emit a brace expansion that will expand any number of arguments.

function braceify {
    [[ $1 == +(digit:) ]] || return
    typeset -a a
    read -ra a < <(factor "$1")
    eval "echo $(printf '{$(printf ,%%.s {1..%s})}' "${a[@]:1}")"
}
printf 'eval printf "$arg"%s' "$(braceify 1000000)"

"Braceify" generates the expansion code itself. In this example we inject that output into a template which displays the most terse brace expansion code that would expand "$arg" 1,000,000 times if evaluated. In this case, the output is:

eval printf "$arg"{,,}{,,}{,,}{,,}{,,}{,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}{,,,,,}

New in Bash 4.0

Zero padded number expansion

Prefix either of the numbers in a numeric range with 0 to pad the expanded numbers with the correct amount of zeros:

$ echo {0001..5}
0001 0002 0003 0004 0005

Increment

It is now possible to specify an increment using ranges:

{<START>..<END>..<INCR>}

<INCR> is numeric, you can use a negative integer but the correct sign is deduced from the order of <START> and <END> anyways.

$ echo {1..10..2}
1 3 5 7 9
$ echo {10..1..2}
10 8 6 4 2

Interesting feature: The increment specification also works for letter-ranges:

$ echo {a..z..3}
a d g j m p s v y

Discussion

Regarding your statement... "Another common pitfall is to assume that a range like {1..200} can be expressed with variables using {$a..$b}."

I get around this by using eval.

$ A=1
$ B=100
$ eval echo ${A..$B}
1 2 3 4 5 6 7 8 9 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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Jan Schampera,
Yes, I know it's possible with eval. I sweared to myself to never really recommend eval, but in this case I'll just "note it" above, so I'm safe :)
Thanks for the feedback.
Rajee,

give some examples for conditional statement n looping..

Jan Schampera,
In here. for brace expansion? Then I don't know what you mean.

Is it possible to access which iteration is currently being used?

For example:

mv {1..5}.something.{1..5} $n1.$n2.something
  • Where $n1 and $n2 are bash's reference to the current iteration

So that this would be it's behavior:

mv 1.something.1 1.1.something
mv 1.something.1 1.2.something
mv 1.something.1 1.3.something

Thanks :D

Jan Schampera,
No, this is not possible. Brace expansion is more like a text macro functionality. It happens before anything else
Daniel,

Is it possible to use brace expansion in a for loop to rename a number of files? If not, why?

Jan Schampera,
It is possible. As in "number generator". What you do with those numbers is independent from this topic:
for i in {1..10}; do
...
done
# equivalent: for i in 1 2 3 4 5 6 7 8 9 10; do
yp,

Is there a nice way to assign the result of the expansion? I know I can use subshell, e.g.

x=$(echo {1..5})

but this is ugly.

In 4.3.11 I can just use this:
x=({1..5})
Result:
echo ${x[@]}
1 2 3 4 5
Charlie Dyson,

The relative order of precedence between brace expansion and subshell piping has changed in Bash 4:

bash3_machine$ paste -d \| <(echo {first,second}) first|second
bash4_machine$ paste -d \| <(echo {first,second}) first second

I found the old behaviour more useful - e.g. for comparing the output of a long chain of commands on two different files.

Jan Schampera,
I'm not sure, but I think this was more like a "bugfix". The new behaviour threats the code inside <() separately. It's more straight forward.
(I don't say this is more useful or useless, I just talk about what I think the reason was)
PhilippePetrinko,

I have noted this additional behavior considering zero padding:

When both start and end range are zero padded, if padding is _different_ , then the longest will be used.

so this will use 6 digits padding, not 3 !

for x in {001..000010} ; do echo “padding :$x:”; done

HTH

– Philippe

Gustav,

The (cute) braceify function has a bug: it must subtract one from each prime factor.

{,,} expands three times, not two.

Also, it wouldn't generate the shortest representation for factors of 4; that'd be {,,,} rather than {,}{,}

@: https://wiki.bash-hackers.org/syntax/expansion/brace

How to Use Brace Expansion in Linux’s Bash Shell

Brace expansion is a useful technique to generate lists of strings that can be used in scripts and aliases and on the Linux command line. Save time and avoid mistakes by typing less.

Brace Expansion

Before the Bash shell executes a command in a terminal window or a line in a script, it checks whether it needs to perform any substitutions on the command. Variable names are replaced by their values, aliases are replaced by the commands they’re shorthand for, and any expansion is performed. Brace expansion is one form of expansion supported by Bash.

Brace expansion is available in modern shells, but it might be missing from some old shells. If you’re going to use brace expansion in scripts, make sure that you invoke a shell that supports brace expansion, such as Bash:

#!/bin/bash

We’ll be using Bash for our examples.

Generating lists of strings might seem more of a novelty than a benefit, but it does offer some functionality that can save time and keystrokes. Often, it can provide a simple and elegant solution to a problem or requirement.

Simple Expansions

A brace expansion is contained between a pair of braces “{}”. It can be a list of comma-separated items or a range specifier. Spaces are not permitted inside the braces unless you’ve wrapped the string in quotation marks “".”

For a comma-separated list, the expansion process takes each element in turn and passes it to the calling command. In this example, it’s echo that simply prints them in the terminal window. Note that the commas are ignored.

echo {one,two,three,four}

A list can be words or digits.

echo {1,2,3,4}

The order of the list elements is completely arbitrary.

echo (4,2,3,1)

An expansion range has a start and an end character connected with two periods ” .. ” without any whitespace. All of the missing list elements are provided automatically by the expansion so that the entire range from start character to end character is created.

This will print the digits from 1 to 10.

The Best Tech Newsletter Anywhere

Join 425,000 subscribers and get a daily digest of features, articles, news, and trivia.

By submitting your email, you agree to the Terms of Use and Privacy Policy.

echo {1..10}

The numbering is arbitrary. It does not have to start at one.

echo {3..12}

Ranges can be specified so that they run backward. This will generate a list from five down to one.

echo {5..1}

Ranges can include negative numbers.

echo {4..-4}

As we previously pointed out, a range has a start and an end character. It doesn’t have to be a number. It can be a letter.

echo {q..v}

The letters can run backward, too.

echo {f..a}

Using Brace Expansion with Loops

You can use brace expansion with ranges in loops in scripts.

for i in {3..7}
do
   echo $i
done

Brace expansion ranges let you use characters as the loop variable.

for i in {m..q}
do
   echo $i
done

Loops are usually used in scripts, but there’s nothing to stop you from typing them into the command line to see what will happen.

for i in {3..7}; do echo $i; done
for i in {m..q}; do echo $i; done

Concatenating and Nesting

Two adjacent expansions don’t act independently one after the other. They interoperate. Each element in the first expansion is acted on by each element in the second expansion.

echo {q..v}{1..3}

Expansions can also be nested. A nested expansion will act on the element immediately preceding it.

echo {part-1,part-2{a,b,c,d},part-3}

Skip advertYou can also nest expansions by creating a comma-delimited list of range expansions.

echo {{5..0},{1..5}}

Preamble and Postscript

You can place text before and after a brace expansion to have that text included in the results of the expansion. Text put in front of an expansion is called the preamble, while text placed behind a brace expansion is called the postscript.

This command uses a preamble.

echo chapter{1..3}

This example uses a postscript:

echo {contents,paper,bilbiography}.md

And this command uses both.

echo chapter-{1..4}.md

Expanding File Names and Directories

As you’ve probably guessed by now, one of the main uses of brace expansions is to create file and directory names that can be passed to other commands. We’ve been using echo as a convenient way to see exactly what happens when an expansion is triggered. You can substitute any command that takes filenames or directory names as input and use brace expansion with it.

To quickly create some files, use touch:

touch file-{1..4}.txt
ls *.txt

If you have many files with the same base name but different file extensions and you want to perform an operation on a subset of them, brace expansions can help. Here, we’re compressing a subset of files that have “program” as the basename into a ZIP file called “source-code.zip.”

Development directories contain lots of files that will have the same basename as your main program. Usually, you don’t want to back up or distribute files like “.o” object files. This is a neat way to only include the file types of interest.

zip source-code program{.c,.h,.css}

This command will make a copy of a file and append “.bak” to it, making a backup copy of the original file. An interesting point to note is that the brace expansion contains a comma-separated list, but the first element is empty. If we hadn’t included the comma, the expansion wouldn’t have taken place.

cp brace/new/prog-1.c{,.bak}
ls brace/new/prog-1.c.bak

To perform some action on two files in different directories, we can use a brace expansion in the path to the files.

In this example, the “brace” directory contains two subdirectories, one called “new” and one called “old.” They contain different versions of the same set of source code files. We’ll use the diff program to see the differences between the two versions of “prog-1.c.”

diff brace/{new,old}/prog-1.c

If you have a standard skeleton of directories that you need to create at the start of a project, you can create them quickly using brace expansion. The  mkdir -p (parent) option creates any missing parent directories when a child directory is created.

mkdir -p {source,build,man,help{/pages,/yelp,/images}}

tree

You can use brace expansion with wget to download multiple files.

In this command, we’re going to download files from two directories, called “test1” and “test2.” Each directory holds two files called “picture1” and “picture2.”

wget https://www.URL-of-your-choice.com/test{1,2}/picture{001,002}.jpg

Listing the files shows you the files that were retrieved and how wget renames files to avoid name clashes with existing files.

ls picture*.*

Embrace the Brace

RELATED15 Special Characters You Need to Know for Bash

It seems that brace expansion is another one of Linux’s best-kept secrets. Many people tell me that they’ve never heard of brace expansion, while others inform me that it’s one of their favorite command-line tricks.

Give it a try and it just might find its way into your set of command-line go-to tricks.

Q: https://www.howtogeek.com/725657/how-to-use-brace-expansion-in-linuxs-bash-shell/