The Beautiful in the Ugly
Published on , 232 words, 1 minutes to read
Functional programming is nice and all, but sometimes you just need to have things get done regardless of the consequences. Sometimes a dirty little hack will suffice in place of a branching construct. This is a story of one of these times.
In shell script, bare words are interpreted as arbitrary commands for the shell to run, interpreted in its rules (simplified to make this story more interesting):
- The first word in a command is the name or path of the program being loaded
- Variable expansions are processed before commands are executed
Given the following snippet of shell script:
#!/bin/sh
# hello.sh
function hello {
echo "hello, $1"
}
$1 $2
When you run this without any arguments:
$ sh ./hello.sh
$
Nothing happens.
Change it to the following:
$ sh ./hello.sh hello world
hello, world
$ sh ./hello.sh ls
hello.sh
Shell commands are bare words. Variable expansion can turn into execution. Normally, this is terrifying. This is useful in fringe cases.
Consider the following script:
#!/bin/sh
# build.sh <action> [arguments]
projbase=github.com/Xe/printerfacts
function gitrev {
git rev-parse HEAD
}
function app {
export GOBIN="$(pwd)"/bin
go install github.com/Xe/printerfacts/cmd/printerfacts
}
function install_system {
app
cp ./bin/printerfacts /usr/local/bin/printerfacts
}
function docker {
docker build -t xena/printerfacts .
docker build -t xena/printerfacts:"$(gitrev)"
}
function deploy {
docker tag xena/printerfacts:"$(gitrev)" registry.heroku.com/printerfacts/web
docker push registry.heroku.com/printerfacts/web
}
$*
Facts and circumstances may have changed since publication. Please contact me before jumping to conclusions if something seems wrong or unclear.
Tags: shell