<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:foaf="https://xmlns.com/foaf/0.1/" xmlns:og="https://ogp.me/ns#" xmlns:rdfs="https://www.w3.org/2000/01/rdf-schema#" xmlns:schema="https://schema.org/" xmlns:sioc="https://rdfs.org/sioc/ns#" xmlns:sioct="https://rdfs.org/sioc/types#" xmlns:skos="https://www.w3.org/2004/02/skos/core#" xmlns:xsd="https://www.w3.org/2001/XMLSchema#" version="2.0" xml:base="https://www.linuxjournal.com/tag/bash">
  <channel>
    <title>Bash</title>
    <link>https://www.linuxjournal.com/tag/bash</link>
    <description/>
    <language>en</language>
    
    <item>
  <title>Writing GitHub Web Hooks with Bash</title>
  <link>https://www.linuxjournal.com/content/writing-github-web-hooks-bash</link>
  <description>  &lt;div data-history-node-id="1340749" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bigstock--164110286.jpg" width="900" height="900" alt="GitHub" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/andy-carlson" lang="" about="https://www.linuxjournal.com/users/andy-carlson" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Andy Carlson&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;Bring your GitHub repository to the next level of functionality.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
For the past year since Microsoft has acquired GitHub, I've been hosting
my Git repositories on a private server. Although I relished the opportunity
and challenge of setting it all up, and the end product works well for my
needs, doing this was not without its sacrifices. GitHub offers a clean interface
for configuring many Git features that otherwise would require more time and
effort than simply clicking a button. One of the features made easier to
implement by GitHub that I was most fond of was web hooks.
A web hook is
executed when a specific event occurs within the GitHub application. Upon
execution, data is sent via an &lt;code&gt;HTTP POST&lt;/code&gt; to a specified URL.
&lt;/p&gt;

&lt;p&gt;
This article
walks through how to set up a custom web hook, including configuring a
web server, processing the POST data from GitHub and creating a few basic
web hooks using Bash.
&lt;/p&gt;

&lt;h3&gt;
Preparing Apache&lt;/h3&gt;

&lt;p&gt;
For the purpose of this project, let's use the Apache web server to host
the web hook scripts. The module that Apache uses to run server-side shell
scripts is &lt;code&gt;mod_cgi&lt;/code&gt;, which is available on major Linux distributions.
&lt;/p&gt;

&lt;p&gt;
Once
the module is enabled, it's time to configure the directory permissions and
virtual host within Apache. Use the /opt/hooks directory to host the
web hooks, and give ownership of this directory to the
user that runs Apache. To determine the user running an Apache instance,
run the following command (provided Apache is currently running):

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
ps -e -o %U%c| grep 'apache2\|httpd'
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
These commands will return a two-column output containing the name of the
user running Apache and the name of the Apache binary (typically either
&lt;code&gt;httpd&lt;/code&gt; or &lt;code&gt;apache2&lt;/code&gt;). Grant directory
permission with the following
&lt;code&gt;chown&lt;/code&gt; command (where &lt;code&gt;USER&lt;/code&gt; is the name of the
user shown in the previous &lt;code&gt;ps&lt;/code&gt; command):

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
chown -R USER /opt/hooks
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Within this directory, two sub-directories will be created: html and
cgi-bin. The html folder will be used as a web root for the virtual host,
and cgi-bin will contain all shell scripts for the virtual host. Be aware
that as new sub-directories and files are created under /opt/hooks, you
may need to rerun the
above &lt;code&gt;chown&lt;/code&gt; to verify proper access to files
and sub-directories.
&lt;/p&gt;

&lt;p&gt;
Here's the configuration for the virtual host within
Apache:

&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/writing-github-web-hooks-bash" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Wed, 07 Aug 2019 16:30:00 +0000</pubDate>
    <dc:creator>Andy Carlson</dc:creator>
    <guid isPermaLink="false">1340749 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>The Bash Trap Command</title>
  <link>https://www.linuxjournal.com/content/bash-trap-command</link>
  <description>  &lt;div data-history-node-id="1340787" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bigstock-Penguin-936090_3.jpg" width="360" height="250" alt="""" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/mitch-frazier" lang="" about="https://www.linuxjournal.com/users/mitch-frazier" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Mitch Frazier&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;If you've written any amount of bash code, you've likely come across the &lt;tt class="docutils literal"&gt;trap&lt;/tt&gt; command. Trap allows you to catch signals and execute code when they occur. Signals are asynchronous notifications that are sent to your script when certain events occur. Most of these notifications are for events that you hope never happen, such as an invalid memory access or a bad system call. However, there are one or two events that you might reasonably want to deal with. There are also "user" events available that are never generated by the system that you can generate to signal your script. Bash also provides a psuedo-signal called "EXIT", which is executed when your script exits; this can be used to make sure that your script executes some cleanup on exit.&lt;/p&gt;
&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/bash-trap-command" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Wed, 07 Aug 2019 15:15:00 +0000</pubDate>
    <dc:creator>Mitch Frazier</dc:creator>
    <guid isPermaLink="false">1340787 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Bash Shell Games: Let's Play Go Fish!</title>
  <link>https://www.linuxjournal.com/content/bash-shell-games-lets-play-go-fish</link>
  <description>  &lt;div data-history-node-id="1340682" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bigstock-Cards-In-The-Hand-4468103%20%281%29.jpg" width="1600" height="969" alt="""" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;How to begin developing a computer version of the popular card game.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
Between the previous 163 columns I've written here in &lt;em&gt;Linux Journal&lt;/em&gt; and the dozens
of games I programmed and explored during the creation of my &lt;em&gt;Wicked Cool
Shell Scripts&lt;/em&gt; book, I've written a lot of Bash shell games. The challenge is to
find one that's simple enough where a shell script will work, but isn't so
simple that it ends up being only a half-dozen lines.
&lt;/p&gt;

&lt;p&gt;
Magic 8-Ball is a perfect example. It turns out that the entire "predict the future" gizmo
was really just a 20-sided die floating in dark purple fluid. So an array of 20 possible
values and a random number selector and boom—you've got a magic 8-ball script:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
#!/bin/sh

# magic 8 ball. Yup. Pick a random number, output message

# messages harvested from the Wikipedia entry

answers=("It is certain." "It is decidedly so."
  "Without a doubt." "Yes - definitely."
  "You may rely on it." "As I see it, yes." "Most likely."
  "Outlook good." "Yes." "Signs point to yes."
  "Reply hazy, try again." "Ask again later."
  "Better not tell you now." "Cannot predict now."
  "Concentrate and ask again." "Don't count on it."
  "My reply is no." "My sources say no."
  "Outlook not so good." "Very doubtful.")

echo "Oh! Magic 8 Ball, Please Tell Me True..." ; echo ""
/bin/echo -n "What is your question? "
read question

answer=$(( $RANDOM % 20 ))

echo ""
echo "I have looked into the future and I say: "
echo "     ${answers[$answer]}" ; echo ""

exit 0
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Let's do a quick run to see if I'm the most popular &lt;em&gt;LJ&lt;/em&gt; writer:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
$ sh magic8.sh
Oh! Magic 8 Ball, Please Tell Me True...

What is your question? Am I the most popular LJ writer?

I have looked into the future and I say:
     My reply is no.
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Ouch, that's harsh. I write the darn divination program, and it just drops a brick on my foot.
Yeesh.
&lt;/p&gt;

&lt;p&gt;
More seriously, Magic 8 Ball is too simple to make an interesting shell script. By
contrast, &lt;em&gt;Call of Duty&lt;/em&gt; is way too complex, even if I did a version with text output
instead of gorgeously rendered 3D graphics.
&lt;/p&gt;

&lt;h3&gt;
Card Game Function Library&lt;/h3&gt;

&lt;p&gt;
That's why card games prove to be good as programming challenges or exercises: the
core mechanism of a 52-card random deck is pretty straightforward, so it's all
about the actual cardplay.
&lt;/p&gt;

&lt;p&gt;
Not only that, but as I've written before about card games as shell scripts, I
already have a handy set of functions to create, shuffle and display cards out of a
deck. If you want to rummage in the archives, I've tackled &lt;em&gt;Acey-Deucey&lt;/em&gt;,
&lt;em&gt;Baccarat&lt;/em&gt;
and some bits and pieces of &lt;em&gt;Cribbage&lt;/em&gt;.
&lt;/p&gt;

&lt;p&gt;
In order to jump right into the new game that I'm going to describe how to build, &lt;em&gt;Go Fish!&lt;/em&gt;,
let's steal the following functions from my earlier scripts:
&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/bash-shell-games-lets-play-go-fish" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Tue, 30 Jul 2019 12:00:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340682 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Job Control: the Bash Feature You Only Think You Don't Need</title>
  <link>https://www.linuxjournal.com/content/job-control-bash-feature-you-only-think-you-dont-need</link>
  <description>  &lt;div data-history-node-id="1340760" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bigstock--224038156_4.jpg" width="900" height="900" alt="""" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/mitch-frazier" lang="" about="https://www.linuxjournal.com/users/mitch-frazier" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Mitch Frazier&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;There are basically three types of people in the world: those who know little or nothing about bash job control, those who know enough to believe that it's nothing that they would ever use, and those who can just skim the rest of this post. Now, don't get me wrong, I'm not saying that bash's job control is going to change your world, but there are a couple simple everyday scenarios where job control can be useful, and often, it even can eliminate an "oh crap" moment.&lt;/p&gt;
&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/job-control-bash-feature-you-only-think-you-dont-need" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Thu, 25 Jul 2019 11:30:00 +0000</pubDate>
    <dc:creator>Mitch Frazier</dc:creator>
    <guid isPermaLink="false">1340760 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Finishing Up the Bash Mail Merge Script</title>
  <link>https://www.linuxjournal.com/content/finishing-bash-mail-merge-script</link>
  <description>  &lt;div data-history-node-id="1340605" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bigstock--224038156_2.jpg" width="900" height="900" alt="""" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;Finally, I'm going to finish the mail merge script, just in time for
Replicant Day.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
Remember the &lt;a href="https://www.linuxjournal.com/content/fun-mail-merge-and-cool-bash-arrays"&gt;mail
merge script&lt;/a&gt; I started writing a while back? Yeah,
that was quite some
time ago. I got sidetracked with the &lt;em&gt;Linux Journal&lt;/em&gt; Anniversary special
issue (see my article &lt;a href="https://www.linuxjournal.com/content/back-day-unix-minix-and-linux"&gt;"Back
in the Day: UNIX, Minix and Linux"&lt;/a&gt;), and then I spun off on a
completely different tangent for my last article (&lt;a href="https://www.linuxjournal.com/content/breaking-apache-log-files-analysis"&gt;"Breaking
Up Apache Log Files for Analysis"&lt;/a&gt;). I blame it on...
&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;SQUIRREL!&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
Oh, sorry, back to topic here. I was developing a shell
script that would let you specify a text document with
embedded field names that could be substituted iteratively
across a file containing lots of field values.
&lt;/p&gt;

&lt;p&gt;
Each field was denoted by &lt;code&gt;#fieldname#&lt;/code&gt;, and I identified two
categories of fieldnames: fixed and dynamic. A fixed value
might be &lt;code&gt;#name#&lt;/code&gt;, which would come directly out of the data
file, while a dynamic value could be &lt;code&gt;#date#&lt;/code&gt;, which would be
the current date.
&lt;/p&gt;
&lt;p&gt;
More interesting, I also proposed calculated values,
specifically &lt;code&gt;#suggested#&lt;/code&gt;, which would be a value calculated
based on &lt;code&gt;#donation#&lt;/code&gt;, and &lt;code&gt;#date#&lt;/code&gt;, which would be replaced by
the current date. The super-fancy version would have a
simple language where you could define the relationship between
variables, but let's get real. Mail merge. It's just mail
merge.
&lt;/p&gt;

&lt;h3&gt;
Reading and Assigning Values&lt;/h3&gt;

&lt;p&gt;
It turns out that the additions needed for this script aren't
too difficult. The basic data file has comma-separated
field names, then subsequent lines have the values
associated with those fields.
&lt;/p&gt;

&lt;p&gt;
Here's that core code:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
if [ $lines -eq 1 ] ; then # field names
# grab variable names
declare -a varname=($f1 $f2 $f3 $f4 $f5 $f6 $f7)
else # process fields

# grab values for this line (can contain spaces)
declare -a value=("$f1" "$f2" "$f3" "$f4" "$f5" "$f6" "$f7")
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
The &lt;code&gt;declare&lt;/code&gt; function turns out to be ideal for this,
allowing you to create an array &lt;code&gt;varname&lt;/code&gt; based on the
contents of the first line, then keep replacing the values
of the array &lt;code&gt;value&lt;/code&gt;, so that &lt;code&gt;varname[1] =
value[1]&lt;/code&gt;, and so
on.
&lt;/p&gt;

&lt;p&gt;
To add the additional variables &lt;code&gt;#date#&lt;/code&gt; and
&lt;code&gt;#suggested#&lt;/code&gt;, you
simply can append them to the &lt;code&gt;varname&lt;/code&gt; and
&lt;code&gt;value&lt;/code&gt; arrays. The
first one is easy, but it did highlight a weakness in the
original code that I had to fix by adding quotes as shown:

&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/finishing-bash-mail-merge-script" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Thu, 04 Jul 2019 12:00:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340605 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>What The @#$%&amp;! (Heck) is this #! (Hash-Bang) Thingy In My Bash Script</title>
  <link>https://www.linuxjournal.com/content/what-heck-hash-bang-thingy-my-bash-script</link>
  <description>  &lt;div data-history-node-id="1340624" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bigstock-Laptop-Programming-Code-On-Sc-280677649_2.jpg" width="900" height="733" alt="bash" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/mitch-frazier" lang="" about="https://www.linuxjournal.com/users/mitch-frazier" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Mitch Frazier&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;You've seen it a million times—the hash-bang (#!) line at the top of a script—whether it be Bash, Python, Perl or some other scripting language. And, I'm sure you know what its purpose is: it specifies the script interpreter that's used to execute the script. But, do you know how it actually works? Your initial thought might be that your shell (bash) reads that line and then executes the specified interpreter, but that's not at all how it works. How it actually works is the main focus of this post, but I also want to introduce how you can create your own version of "hash-bang" if you're so inclined.&lt;/p&gt;
&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/what-heck-hash-bang-thingy-my-bash-script" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Fri, 10 May 2019 11:30:00 +0000</pubDate>
    <dc:creator>Mitch Frazier</dc:creator>
    <guid isPermaLink="false">1340624 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Pattern Matching In Bash</title>
  <link>https://www.linuxjournal.com/content/pattern-matching-bash</link>
  <description>  &lt;div data-history-node-id="1340555" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bigstock-Laptop-Programming-Code-On-Sc-280677649_1.jpg" width="900" height="733" alt="bash" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/mitch-frazier" lang="" about="https://www.linuxjournal.com/users/mitch-frazier" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Mitch Frazier&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Wildcards have been around forever. Some even claim they appear in the hieroglyphics of the ancient Egyptians. Wildcards allow you to specify succinctly a pattern that matches a set of filenames (for example, &lt;tt class="docutils literal"&gt;*.pdf&lt;/tt&gt; to get a list of all the PDF files). Wildcards are also often referred to as glob patterns (or when using them, as "globbing"). But glob patterns have uses beyond just generating a list of useful filenames. The bash man page refers to glob patterns simply as "Pattern Matching".&lt;/p&gt;
&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/pattern-matching-bash" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Mon, 15 Apr 2019 11:30:00 +0000</pubDate>
    <dc:creator>Mitch Frazier</dc:creator>
    <guid isPermaLink="false">1340555 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Fun with Mail Merge and Cool Bash Arrays</title>
  <link>https://www.linuxjournal.com/content/fun-mail-merge-and-cool-bash-arrays</link>
  <description>  &lt;div data-history-node-id="1340460" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bigstock-Terminal-startup-icon-direct--90816239_5.jpg" width="600" height="600" alt="""" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;Creating a sed-based file substitution tool.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
A few weeks ago, I was digging through my spam folder and found an email message
that started out like this:
&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
Dear #name#
Congratulations on winning the $15.7 million lottery payout!
To learn how to claim your winnings, please...
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Obviously, it was a scam (does anyone actually fall for these?), but what captured my
attention was the &lt;code&gt;#name#&lt;/code&gt; sequence. Clearly that was a fail on the part of the sender who
presumably didn't know how to use AnnoyingSpamTool 1.3 or whatever the heck
he or she was using.
&lt;/p&gt;

&lt;p&gt;
The more general notation for bulk email and file transformations is pretty
interesting, however. There are plenty of legitimate reasons to use this sort
of substitution, ranging from email newsletters (like the one I send every week
from &lt;a href="https://www.askdavetaylor.com"&gt;AskDaveTaylor.com&lt;/a&gt;—check it out!) to stockholder announcements and much
more.
&lt;/p&gt;

&lt;p&gt;
With that as the inspiration, let's build a tool that offers just this
capability.
&lt;/p&gt;

&lt;p&gt;
The simple version will be a 1:1 substitution, so &lt;code&gt;#name#&lt;/code&gt; becomes, say,
"Rick Deckard", while &lt;code&gt;#first#&lt;/code&gt; might be "Rick" and
&lt;code&gt;#last#&lt;/code&gt; might
be "Deckard". Let's build on that, but let's start
small.
&lt;/p&gt;

&lt;h3&gt;
Simple Word Substitution in Linux&lt;/h3&gt;

&lt;p&gt;
There are plenty of ways to tackle the word substitution from the command line,
ranging from Perl to awk, but here I'm using the original UNIX command
&lt;code&gt;sed&lt;/code&gt; (stream editor) designed for exactly this purpose. General notation for a
substitution is s/old/new/, and if you tack on a &lt;code&gt;g&lt;/code&gt; at the end, it
matches every occurrence on a line, not only the first, so the full command
is s/old/new/g.
&lt;/p&gt;

&lt;p&gt;
Before going further, here's a simple document that has necessary
substitutions embedded:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
$ cat convertme.txt
#date#

Dear #name#, I wanted to start by again thanking you for your
generous donation of #amount# in #month#. We couldn't do our
work without support from humans like you, #first#.

This year we're looking at some unexpected expenses,
particularly in Sector 5, which encompasses #state#, as you
know. I'm hoping you can start the year with an additional
contribution? Even #suggested# would be tremendously helpful.

Thanks for your ongoing support. With regards,

Rick Deckard
Society for the Prevention of Cruelty to Replicants
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Scan through it, and you'll see there's a lot of substitutions to do:
&lt;code&gt;#date#&lt;/code&gt;, &lt;code&gt;#name#&lt;/code&gt;,
&lt;code&gt;#amount#&lt;/code&gt;, &lt;code&gt;#month#&lt;/code&gt;, &lt;code&gt;#first#&lt;/code&gt;,
&lt;code&gt;#state#&lt;/code&gt; and &lt;code&gt;#suggested#&lt;/code&gt;. It turns out that
&lt;code&gt;#date#&lt;/code&gt; will
be replaced with the current date, and &lt;code&gt;#suggested#&lt;/code&gt; is one that'll be
calculated as the letter is processed, but that's for a bit later, so
stay tuned for that.
&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/fun-mail-merge-and-cool-bash-arrays" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Mon, 25 Mar 2019 11:30:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340460 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Cat-Proofing Your Screen Locker with Bash</title>
  <link>https://www.linuxjournal.com/content/cat-proofing-your-screen-locker</link>
  <description>  &lt;div data-history-node-id="1340483" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bigstock-Cat-Walk-On-Wooden-Desk-With-L-260696149.jpg" width="900" height="675" alt="cat walking on computer" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/mitch-frazier" lang="" about="https://www.linuxjournal.com/users/mitch-frazier" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Mitch Frazier&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;I have a computer in my bedroom. I also have cats. Unfortunately, cats and screen lockers don't mix well, particularly at night. To be accurate, it's more a problem with the display power management than the actual screen locking. Here's the way it works: I run a script to "shut the lights off at night" (that is, lock the screen and force the display to power down), and that works great, until one of the cats jumps on the desk and causes the mouse to move and turn the display back on. And the cats don't even have to touch the mouse; the slight movement of the desk is enough to cause the mouse to react. Recently, I'd had enough of it and figured there had to be a way to disable the mouse and "refactor" the script.&lt;/p&gt;
&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/cat-proofing-your-screen-locker" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Wed, 20 Feb 2019 13:00:00 +0000</pubDate>
    <dc:creator>Mitch Frazier</dc:creator>
    <guid isPermaLink="false">1340483 at https://www.linuxjournal.com</guid>
    </item>
<item>
  <title>Converting Decimals to Roman Numerals with Bash</title>
  <link>https://www.linuxjournal.com/content/converting-decimals-roman-numerals-bash</link>
  <description>  &lt;div data-history-node-id="1340357" class="layout layout--onecol"&gt;
    &lt;div class="layout__region layout__region--content"&gt;
      
            &lt;div class="field field--name-field-node-image field--type-image field--label-hidden field--item"&gt;  &lt;img src="https://www.linuxjournal.com/sites/default/files/nodeimage/story/bash-icon_4.png" width="600" height="600" alt="bash" typeof="foaf:Image" class="img-responsive" /&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-author field--type-ds field--label-hidden field--item"&gt;by &lt;a title="View user profile." href="https://www.linuxjournal.com/users/dave-taylor" lang="" about="https://www.linuxjournal.com/users/dave-taylor" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;Dave Taylor&lt;/a&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;&lt;em&gt;Decimals to Roman numerals—here we hit all the limitations of Bash
shell scripting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
My last few articles have given me a chance to relive my undergraduate
computer science degree and code a Roman numeral to decimal converter.
It's quite handy when you're watching old movies (when was MCMLVII
anyway?), and
the basic coding algorithm was reasonably straightforward. (See Dave's &lt;a href="https://www.linuxjournal.com/content/roman-numerals-and-bash"&gt;"Roman
Numerals and Bash"&lt;/a&gt; and &lt;a href="https://www.linuxjournal.com/content/more-roman-numerals-and-bash"&gt;"More
Roman Numerals and Bash"&lt;/a&gt;.)
&lt;/p&gt;

&lt;p&gt;
The trick with Roman numerals, however, is that it's what's known
as a &lt;em&gt;subtractive notation&lt;/em&gt;. In other words, it's not a position → value
or even symbol → value notation, but a sort of hybrid. MM = 2000, and C =
100, but MMC and MCM are quite different: the former is 2100, and the
latter is 1000 + (–100 + 1000) = 1900.
&lt;/p&gt;

&lt;p&gt;
This means that the conversion isn't quite as simple as a mapping
table, which makes it a good homework assignment for young comp-sci
students!
&lt;/p&gt;

&lt;h3&gt;
Let's Write Some Code&lt;/h3&gt;

&lt;p&gt;
In the Roman numeral to decimal conversion, a lot of the key work was done
by this simple function:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
mapit() {
   case $1 in
     I|i) value=1 ;;
     V|v) value=5 ;;
     X|x) value=10 ;;
     L|l) value=50 ;;
     C|c) value=100 ;;
     D|d) value=500 ;;
     M|m) value=1000 ;;
      * ) echo "Error: Value $1 unknown" &gt;&amp;2 ; exit 2 ;;
   esac
}
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
You'll need this function to proceed, but as a cascading set of
conditional statements. Indeed, in its simple form, you could code a decimal to Roman
numeral converter like this:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
while [ $decvalue -gt 0 ] ; do

  if [ $decvalue -gt 1000 ] ; then
    romanvalue="$romanvalue M"
    decvalue=$(( $decvalue - 1000 ))
  elif [ $decvalue -gt 500 ] ; then
    romanvalue="$romanvalue D"
    decvalue=$(( $decvalue - 500 ))
  elif [ $decvalue -gt 100 ] ; then
    romanvalue="$romanvalue C"
    decvalue=$(( $decvalue - 100 ))
  elif [ $decvalue -gt 50 ] ; then
    romanvalue="$romanvalue L"
    decvalue=$(( $decvalue - 50 ))
  elif [ $decvalue -gt 10 ] ; then
    romanvalue="$romanvalue X"
    decvalue=$(( $decvalue - 10 ))
  elif [ $decvalue -gt 5 ] ; then
    romanvalue="$romanvalue V"
    decvalue=$(( $decvalue - 5 ))
  elif [ $decvalue -ge 1 ] ; then
    romanvalue="$romanvalue I"
    decvalue=$(( $decvalue - 1 ))
  fi

done
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
This actually works, though the results are, um, a bit clunky:

&lt;/p&gt;&lt;pre&gt;
&lt;code&gt;
$ sh 2roman.sh 25
converts to roman numeral  X X I I I I I
&lt;/code&gt;
&lt;/pre&gt;


&lt;p&gt;
Or, more overwhelming:

&lt;/p&gt;&lt;/div&gt;
      
            &lt;div class="field field--name-node-link field--type-ds field--label-hidden field--item"&gt;  &lt;a href="https://www.linuxjournal.com/content/converting-decimals-roman-numerals-bash" hreflang="en"&gt;Go to Full Article&lt;/a&gt;
&lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;

</description>
  <pubDate>Mon, 18 Feb 2019 12:30:00 +0000</pubDate>
    <dc:creator>Dave Taylor</dc:creator>
    <guid isPermaLink="false">1340357 at https://www.linuxjournal.com</guid>
    </item>

  </channel>
</rss>
