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