Friday, 10 September 2021

TIL - building bash using cat and tee and EOF

So I've started to make more use of cat and tee and the EOF symbol when creating documentation describing how one can create various different artefacts from, say, Bash on Linux and macOS.

Typically, I'm focusing upon configuration files e.g. files with .conf and .yaml but, a few days back, I wanted to create a Bash script.

Here's an example of what I'd do for a containerd.conf configuration file: -

cat <<EOF | tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

Nice and simple, right ?

I then tried the same for a Bash script, here's a trivial example that munges a JSON document - me.json : -

{
    "name": "Dave Hay",
    "eddress": "david_hay@uk.ibm.com",
    "github": "davidhay1969"
}

called ./hello.sh created thusly: -

cat << EOF | tee hello.sh
#!/bin/bash
name=$(cat ~/me.json | jq -r .name)
echo "Hello, "$name
EOF

So, when I paste that into a macOS Terminal session, using /bin/bash this is what I see: -

cat << EOF | tee hello.sh
> #!/bin/bash
> name=$(cat ~/me.json | jq -r .name)
> echo "Hello, "$name
> EOF
#!/bin/bash
name=Dave Hay
echo "Hello, "

with the resulting script looking a bit ... weird ...

cat hello.sh

#!/bin/bash
name=Dave Hay
echo "Hello, "

Having made the script executable: -

chmod +x hello.sh

it doesn't run too well: -

./hello.sh

./hello.sh: line 2: Hay: command not found
Hello,

Thankfully, when I hit the original issue a few days back, something I read ( and, alas, I didn't grab the actual source ), the trick is to wrap the first EOF in single quotes, like this: -

cat << 'EOF' | tee hello.sh
#!/bin/bash
name=$(cat ~/me.json | jq -r .name)
echo "Hello, "$name
EOF

This is what happens when I paste the above into the same Terminal Bash session: -

cat << 'EOF' | tee hello.sh
> #!/bin/bash
> name=$(cat ~/me.json | jq -r .name)
> echo "Hello, "$name
> EOF
#!/bin/bash
name=$(cat ~/me.json | jq -r .name)
echo "Hello, "$name

and the corresponding script looks OK: -

cat hello.sh

#!/bin/bash
name=$(cat ~/me.json | jq -r .name)
echo "Hello, "$name

and, even better, it actually works: -

./hello.sh

Hello, Dave Hay

Can you say "Yay" ?

No comments:

Yay, VMware Fusion and macOS Big Sur - no longer "NAT good friends" - forgive the double negative and the terrible pun ...

After macOS 11 Big Sur was released in 2020, VMware updated their Fusion product to v12 and, sadly, managed to break Network Address Trans...