I’m quite a huge fan of functional programming, since I learnt about it some years ago. I was doing imperative programming for years and was quite used to it. But learning a new way to conceptualize programs was a real pleasure. Now that I’m deep into it, I want to apply it everywhere, even in the most unexpected places. Today, let’s bring it to the POSIX shell (sh)!

First, we need to see how sh is shaped

  • a program is a function
    • its arguments mostly determine its behavior
  • output of a program is the return value
    • we can’t use only the return code as it’s not encoding much information
  • we can map and filter by piping

The only remaining trick is a way to go from output to function’s arguments. Here comes xargs. For a reminder, xargs reads stdin and puts each space-separated word as an argument of the given command. For example, echo some random files | xargs cat is equivalent to cat some random files.

We now have everything we need to write some functional sh, let’s have some fun with it!

You where doing loop, pfff, what about a number iterator where we map what we want:

for i in $(seq 10); do echo $i; done
# vs
seq 10 | xargs -n1 echo
# xargs -n1 means to run the cmd each 1 argument

Want to convert your MP4 files to MP3?

for file in *.mp4
do
    name=$(echo $file | cut -d . -f 1)
    ffmpeg -i $name.mp4 $name.mp3
done
# vs
ls *.mp4 |
    cut -d . -f 1 |
    xargs -I{} ffmpeg -i {}.mp4 {}.mp3

Ho, and you wanted to do the last one concurrently? Look for --max-procs in xargs!
And if you really want to still have some imperative coding, you can read from the pipe with while read line (but you shouldn’t).

There are still a bunch of other coding structures that you can find in sh. It’s an underrated language, seen as glue-code and not really learned, but it is strangely powerful. Look for small structures in classical languages that you can use to approach the most and greatest ever language paradigm functional programming, try these out; don’t let the language dictate how you see your code!

For some other approaches to functional shell scripting, read the following articles:
https://haskellrescue.blogspot.com/2011/11/bash-monad.html
https://okmij.org/ftp/Computation/monadic-shell.html


tharvik