Generating the Fibonacci Sequence in One Line of Bash

During the later half of my undergrad I spent a lot of time doodling with bash scripts when I got bored in class. One day I challenged myself to write an algorithm that generates the fibonacci sequence using only a single line of bash.

Here's the whole thing without any formatting.

printf "1\n1\n" | tee -a fib_out && seq $(expr $1 - 2) | xargs -n 1 sh -c 'echo $(expr $(tail -n 1 fib_out) + $(tail -n 2 fib_out | head -n 1)) | tee -a fib_out' && rm fib_out

This is a lot to take in all in one line, so let's break it down piece by piece. Here's what it looks like when you display every command between the `&&` operators on their own separate lines.

printf "1\n1\n" | tee -a fib_out && seq $(expr $1 - 2) | xargs -n 1 \
    sh -c 'echo $(expr $(tail -n 1 fib_out) + $(tail -n 2 fib_out | head -n 1)) \
    | tee -a fib_out' && rm fib_out

Here's the first segment of the command before the first `&&` operator.

printf "1\n1\n" | tee -a fib_out

This writes two ones separated by a newline to the beginning of the `fib_out` file. After this we are setup to calculate the next Fibonacci numbers because we have the first two defined.

seq $(expr $1 - 2)

The `expr` command allows us to perform mathematical operations on the command line. This allows us to invoke the `seq` command (which generates numbers from 1 to N) with a calculated N value. We subtract 2 from N because we have already calculated the first two Fibonacci numbers with our `printf` invocation.

After we have setup the `fib_out` file with the first two numbers we `xargs` command to calculate all further numbers.

xargs -n 1 sh -c '...'

The `xargs` command will run the specified command on every line read from stdin until an EOT or EOF is encountered. We use the `-n` flag here to specify that only one line will be read by each process. So what's in the specified command after the `-c` flag? Here's the command we use to parse two numbers from the file and calculate the next Fibonacci number:

echo $(expr $(tail -n 1 fib_out) + $(tail -n 2 fib_out | head -n 1)) | tee -a fib_out

We use the `expr` command again to add the last two numbers in the file together. The last number is retrieved by using `tail` to print the last `n` lines of the file. When we invoke `tail -n 1` we are specifying that we only need to see the very last line of the file. To get the second to last line of the file, we can combine `head` and `tail`. The `head` command serves as the inverse of the `tail` command. Instead of printing the last `n` lines, it prints the first `n` lines of the specified file. The expression on the right hand side of the operator is created by grabbing the last two lines of the `fib_out` file and then using the `head` command to read the first line from STDIN. Once we have calculated the sum of the last two Fibonacci numbers, we can append the result to the `fib_out` file using the `tee` operator.

Once we have finished writing all the numbers to the console, we remove the `fib_out` script with the `rm` command and exit the program.