03-26-2019, 05:48 PM
Using Square Brackets in Bash: Part 1
<div style="margin: 5px 5% 10px 5%;"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/03/using-square-brackets-in-bash-part-1.jpg" width="1255" height="853" title="" alt="" /></div><div><div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/03/using-square-brackets-in-bash-part-1.jpg" class="ff-og-image-inserted"></div>
<p>After taking a look at <a href="https://www.linux.com/blog/learn/2019/2/all-about-curly-braces-bash">how curly braces (<code>{}</code>) work on the command line</a>, now it’s time to tackle brackets (<code>[]</code>) and see how they are used in different contexts.</p>
<h3>Globbing</h3>
<p>The first and easiest use of square brackets is in <em>globbing</em>. You have probably used globbing before without knowing it. Think of all the times you have listed files of a certain type, say, you wanted to list JPEGs, but not PNGs:</p>
<pre>
ls *.jpg</pre>
<p>Using wildcards to get all the results that fit a certain pattern is precisely what we call globbing.</p>
<p>In the example above, the asterisk means “<i>zero or more characters</i>“. There is another globbing wildcard, <code>?</code>, which means “<i>exactly one character</i>“, so, while</p>
<pre> ls d*k*
</pre>
<p>will list files called <i>darkly</i> and <i>ducky</i> (and <i>dark</i> and <i>duck</i> — remember <code>*</code> can also be zero characters),</p>
<pre> ls d*k? </pre>
<p>will not list <i>darkly</i> (or <i>dark</i> or <i>duck</i>), but it will list <i>ducky</i>.</p>
<p>Square brackets are used in globbing for sets of characters. To see what this means, make directory in which to carry out tests, <code>cd</code> into it and create a bunch of files like this:</p>
<pre> touch file0{0..9}{0..9} </pre>
<p>(If you don’t know why that works, <a href="https://www.linux.com/blog/learn/2019/2/all-about-curly-braces-bash">take a look at the last installment that explains curly braces <code>{}</code></a>).</p>
<p>This will create files <i>file000</i>, <i>file001</i>, <i>file002</i>, etc., through <i>file097</i>, <i>file098</i> and <i>file099</i>.</p>
<p>Then, to list the files in the 70s and 80s, you can do this:</p>
<pre> ls file0[78]? </pre>
<p>To list <i>file022</i>, <i>file027</i>, <i>file028</i>, <i>file052</i>, <i>file057</i>, <i>file058</i>, <i>file092</i>, <i>file097</i>, and <i>file98</i> you can do this:</p>
<pre> ls file0[259][278] </pre>
<p>Of course, you can use globbing (and square brackets for sets) for more than just <code>ls</code>. You can use globbing with any other tool for listing, removing, moving, or copying files, although the last two may require a bit of lateral thinking.</p>
<p>Let’s say you want to create duplicates of files <i>file010</i> through <i>file029</i> and call the copies <i>archive010</i>, <i>archive011</i>, <i>archive012</i>, etc..</p>
<p>You can’t do:</p>
<pre> cp file0[12]? archive0[12]? </pre>
<p>Because globbing is for matching against existing files and directories and the <i>archive…</i> files don’t exist yet.</p>
<p>Doing this:</p>
<pre> cp file0[12]? archive0[1..2][0..9] </pre>
<p>won’t work either, because <code>cp</code> doesn’t let you copy many files to other many new files. Copying many files only works if you are copying them to a directory, so this:</p>
<pre> mkdir archive cp file0[12]? archive </pre>
<p>would work, but it would copy the files, using their same names, into a directory called <i>archive/</i>. This is not what you set out to do.</p>
<p>However, if you look back at <a href="https://www.linux.com/blog/learn/2019/2/all-about-curly-braces-bash">the article on curly braces (<code>{}</code>)</a>, you will remember how you can use <code>%</code> to lop off the end of a string contained in a variable.</p>
<p>Of course, there is a way you can also lop of the beginning of string contained in a variable. Instead of <code>%</code>, you use <code>#</code>.</p>
<p>For practice, you can try this:</p>
<pre> myvar="Hello World" echo Goodbye Cruel ${myvar#Hello} </pre>
<p>It prints “<i>Goodbye Cruel World</i>” because <code>#Hello</code> gets rid of the <i>Hello</i> part at the beginning of the string stored in <code>myvar</code>.</p>
<p>You can use this feature alongside your globbing tools to make your <i>archive</i> duplicates:</p>
<pre> for i in file0[12]?;\ do\ cp $i archive${i#file};\ done </pre>
<p>The first line tells the Bash interpreter that you want to loop through all the files that contain the string <i>file0</i> followed by the digits <i>1</i> or <i>2</i>, and then one other character, which can be anything. The second line <code>do</code> indicates that what follows is the instruction or list of instructions you want the interpreter to loop through.</p>
<p>Line 3 is where the actually copying happens, and you use the contents of the loop variable <em><code>i</code></em><em> </em>twice: First, straight out, as the first parameter of the <code>cp</code> command, and then you add <i>archive</i> to its contents, while at the same time cutting of <i>file</i>. So, if <em><code>i</code></em> contains, say, <i>file019</i>…</p>
<pre> "archive" + "file019" - "file" = "archive019" </pre>
<p>the <code>cp</code> line is expanded to this:</p>
<pre> cp file019 archive019 </pre>
<p>Finally, notice how you can use the backslash <code>\</code> to split a chain of commands over several lines for clarity.</p>
<p>In part two, we’ll look at more ways to use square brackets. Stay tuned.</p>
</div>
<div style="margin: 5px 5% 10px 5%;"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/03/using-square-brackets-in-bash-part-1.jpg" width="1255" height="853" title="" alt="" /></div><div><div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/03/using-square-brackets-in-bash-part-1.jpg" class="ff-og-image-inserted"></div>
<p>After taking a look at <a href="https://www.linux.com/blog/learn/2019/2/all-about-curly-braces-bash">how curly braces (<code>{}</code>) work on the command line</a>, now it’s time to tackle brackets (<code>[]</code>) and see how they are used in different contexts.</p>
<h3>Globbing</h3>
<p>The first and easiest use of square brackets is in <em>globbing</em>. You have probably used globbing before without knowing it. Think of all the times you have listed files of a certain type, say, you wanted to list JPEGs, but not PNGs:</p>
<pre>
ls *.jpg</pre>
<p>Using wildcards to get all the results that fit a certain pattern is precisely what we call globbing.</p>
<p>In the example above, the asterisk means “<i>zero or more characters</i>“. There is another globbing wildcard, <code>?</code>, which means “<i>exactly one character</i>“, so, while</p>
<pre> ls d*k*
</pre>
<p>will list files called <i>darkly</i> and <i>ducky</i> (and <i>dark</i> and <i>duck</i> — remember <code>*</code> can also be zero characters),</p>
<pre> ls d*k? </pre>
<p>will not list <i>darkly</i> (or <i>dark</i> or <i>duck</i>), but it will list <i>ducky</i>.</p>
<p>Square brackets are used in globbing for sets of characters. To see what this means, make directory in which to carry out tests, <code>cd</code> into it and create a bunch of files like this:</p>
<pre> touch file0{0..9}{0..9} </pre>
<p>(If you don’t know why that works, <a href="https://www.linux.com/blog/learn/2019/2/all-about-curly-braces-bash">take a look at the last installment that explains curly braces <code>{}</code></a>).</p>
<p>This will create files <i>file000</i>, <i>file001</i>, <i>file002</i>, etc., through <i>file097</i>, <i>file098</i> and <i>file099</i>.</p>
<p>Then, to list the files in the 70s and 80s, you can do this:</p>
<pre> ls file0[78]? </pre>
<p>To list <i>file022</i>, <i>file027</i>, <i>file028</i>, <i>file052</i>, <i>file057</i>, <i>file058</i>, <i>file092</i>, <i>file097</i>, and <i>file98</i> you can do this:</p>
<pre> ls file0[259][278] </pre>
<p>Of course, you can use globbing (and square brackets for sets) for more than just <code>ls</code>. You can use globbing with any other tool for listing, removing, moving, or copying files, although the last two may require a bit of lateral thinking.</p>
<p>Let’s say you want to create duplicates of files <i>file010</i> through <i>file029</i> and call the copies <i>archive010</i>, <i>archive011</i>, <i>archive012</i>, etc..</p>
<p>You can’t do:</p>
<pre> cp file0[12]? archive0[12]? </pre>
<p>Because globbing is for matching against existing files and directories and the <i>archive…</i> files don’t exist yet.</p>
<p>Doing this:</p>
<pre> cp file0[12]? archive0[1..2][0..9] </pre>
<p>won’t work either, because <code>cp</code> doesn’t let you copy many files to other many new files. Copying many files only works if you are copying them to a directory, so this:</p>
<pre> mkdir archive cp file0[12]? archive </pre>
<p>would work, but it would copy the files, using their same names, into a directory called <i>archive/</i>. This is not what you set out to do.</p>
<p>However, if you look back at <a href="https://www.linux.com/blog/learn/2019/2/all-about-curly-braces-bash">the article on curly braces (<code>{}</code>)</a>, you will remember how you can use <code>%</code> to lop off the end of a string contained in a variable.</p>
<p>Of course, there is a way you can also lop of the beginning of string contained in a variable. Instead of <code>%</code>, you use <code>#</code>.</p>
<p>For practice, you can try this:</p>
<pre> myvar="Hello World" echo Goodbye Cruel ${myvar#Hello} </pre>
<p>It prints “<i>Goodbye Cruel World</i>” because <code>#Hello</code> gets rid of the <i>Hello</i> part at the beginning of the string stored in <code>myvar</code>.</p>
<p>You can use this feature alongside your globbing tools to make your <i>archive</i> duplicates:</p>
<pre> for i in file0[12]?;\ do\ cp $i archive${i#file};\ done </pre>
<p>The first line tells the Bash interpreter that you want to loop through all the files that contain the string <i>file0</i> followed by the digits <i>1</i> or <i>2</i>, and then one other character, which can be anything. The second line <code>do</code> indicates that what follows is the instruction or list of instructions you want the interpreter to loop through.</p>
<p>Line 3 is where the actually copying happens, and you use the contents of the loop variable <em><code>i</code></em><em> </em>twice: First, straight out, as the first parameter of the <code>cp</code> command, and then you add <i>archive</i> to its contents, while at the same time cutting of <i>file</i>. So, if <em><code>i</code></em> contains, say, <i>file019</i>…</p>
<pre> "archive" + "file019" - "file" = "archive019" </pre>
<p>the <code>cp</code> line is expanded to this:</p>
<pre> cp file019 archive019 </pre>
<p>Finally, notice how you can use the backslash <code>\</code> to split a chain of commands over several lines for clarity.</p>
<p>In part two, we’ll look at more ways to use square brackets. Stay tuned.</p>
</div>