Bash: It's Cows All the Way Down

21 Nov 2016
 __________________________________
/  ______________________________  \
| /  _____                       \ |
| | < moo >                      | |
| |  -----                       | |
| |         \   ^__^             | |
| |          \  (oo)\_______     | |
| |             (__)\       )\/\ | |
| |                 ||----w |    | |
| \                 ||     ||    / |
|  ------------------------------  |
|         \   ^__^                 |
|          \  (oo)\_______         |
|             (__)\       )\/\     |
|                 ||----w |        |
\                 ||     ||        /
 ----------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

If you wanted to compose cows together you could run echo moo | cowsay -n | cowsay -n | cowsay -n [1] to pipe three cows as shown above.

If however you wanted to compose an arbitrary number of cows, you would need to write a looping construct as shown below:

bad_cows() {
  text=$1
  num_cows=$2
  output=$text
  for ((i=0; i<$num_cows; i++)); do
      output=$(echo $output | cowsay -n)
  done
  echo $output
}

Calling bad_cows moo 3 gives:

_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________ < ______________________________________________________________________ < _____ < moo > ----- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || > ---------------------------------------------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || > ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||

... That's not quite right.

Lets check the IFS, or Internal Field Separator to find out why.

> printf '%q' "$IFS"
$' \t\n'

Unfortunately for me, Bash's IFS operator is set interpret spaces, newlines, and tabs as field separators (separators for arguments) so that these values are replaced if the string is not quoted:

cows_all_the_way_down() {
    text="$1"
    num_cows=$2
    output="$text"
    for ((i=0; i<$num_cows; i++)); do
        output="$(echo "$output" | cowsay -n)"
    done
    echo "$output"
}

Now cows_all_the_way_down moo 3 gives the same result as piping cowsay three times because newlines, spaces, and tabs are preserved.

Another way to achieve the same affect is to locally set IFS to the empty string so that no value is interpreted as an argument separator:

ifs_cows() {
    local IFS=
    text=$1
    num_cows=$2
    output=$text
    for ((i=0; i<$num_cows; i++)); do
        output=$(echo $output | cowsay -n)
    done
    echo $output
}

The local keyword allows function variables to mask global or environment variables for the duration of the function call. Setting the IFS to an empty string means that we do not have to worry about quoting. And the local keyword will leave the value of the environment variable IFS untouched.

For bonus, here's how to solve your cow needs recursively:

recursive_cows() {
    local IFS=
    text=$1
    num_cows=$2
    output=$(echo $text | cowsay -n)
    if (( num_cows <= 1 )); then
        echo $output
    else
        recursive_cows $output $(($num_cows - 1))
    fi
}

recursive_cows moo 40

 ______________________________________________________________________________________________________
/  __________________________________________________________________________________________________  \
| /  ______________________________________________________________________________________________  \ |
| | /  __________________________________________________________________________________________  \ | |
| | | /  ______________________________________________________________________________________  \ | | |
| | | | /  __________________________________________________________________________________  \ | | | |
| | | | | /  ______________________________________________________________________________  \ | | | | |
| | | | | | /  __________________________________________________________________________  \ | | | | | |
| | | | | | | /  ______________________________________________________________________  \ | | | | | | |
| | | | | | | | /  __________________________________________________________________  \ | | | | | | | |
| | | | | | | | | /  ______________________________________________________________  \ | | | | | | | | |
| | | | | | | | | | /  __________________________________________________________  \ | | | | | | | | | |
| | | | | | | | | | | /  ______________________________________________________  \ | | | | | | | | | | |
| | | | | | | | | | | | /  __________________________________________________  \ | | | | | | | | | | | |
| | | | | | | | | | | | | /  ______________________________________________  \ | | | | | | | | | | | | |
| | | | | | | | | | | | | | /  __________________________________________  \ | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | /  ______________________________________  \ | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | /  __________________________________  \ | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | /  ______________________________  \ | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | /  _____                       \ | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | < moo >                      | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | |  -----                       | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | |         \   ^__^             | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | |          \  (oo)\_______     | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | |             (__)\       )\/\ | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | |                 ||----w |    | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | \                 ||     ||    / | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |  ------------------------------  | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |         \   ^__^                 | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |          \  (oo)\_______         | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |             (__)\       )\/\     | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | |                 ||----w |        | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | \                 ||     ||        / | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |  ----------------------------------  | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |         \   ^__^                     | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |          \  (oo)\_______             | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |             (__)\       )\/\         | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |                 ||----w |            | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | \                 ||     ||            / | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | |  --------------------------------------  | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | |         \   ^__^                         | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | |          \  (oo)\_______                 | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | |             (__)\       )\/\             | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | |                 ||----w |                | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | \                 ||     ||                / | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |  ------------------------------------------  | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |         \   ^__^                             | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |          \  (oo)\_______                     | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |             (__)\       )\/\                 | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | |                 ||----w |                    | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | \                 ||     ||                    / | | | | | | | | | | | | | |
| | | | | | | | | | | | | |  ----------------------------------------------  | | | | | | | | | | | | | |
| | | | | | | | | | | | | |         \   ^__^                                 | | | | | | | | | | | | | |
| | | | | | | | | | | | | |          \  (oo)\_______                         | | | | | | | | | | | | | |
| | | | | | | | | | | | | |             (__)\       )\/\                     | | | | | | | | | | | | | |
| | | | | | | | | | | | | |                 ||----w |                        | | | | | | | | | | | | | |
| | | | | | | | | | | | | \                 ||     ||                        / | | | | | | | | | | | | |
| | | | | | | | | | | | |  --------------------------------------------------  | | | | | | | | | | | | |
| | | | | | | | | | | | |         \   ^__^                                     | | | | | | | | | | | | |
| | | | | | | | | | | | |          \  (oo)\_______                             | | | | | | | | | | | | |
| | | | | | | | | | | | |             (__)\       )\/\                         | | | | | | | | | | | | |
| | | | | | | | | | | | |                 ||----w |                            | | | | | | | | | | | | |
| | | | | | | | | | | | \                 ||     ||                            / | | | | | | | | | | | |
| | | | | | | | | | | |  ------------------------------------------------------  | | | | | | | | | | | |
| | | | | | | | | | | |         \   ^__^                                         | | | | | | | | | | | |
| | | | | | | | | | | |          \  (oo)\_______                                 | | | | | | | | | | | |
| | | | | | | | | | | |             (__)\       )\/\                             | | | | | | | | | | | |
| | | | | | | | | | | |                 ||----w |                                | | | | | | | | | | | |
| | | | | | | | | | | \                 ||     ||                                / | | | | | | | | | | |
| | | | | | | | | | |  ----------------------------------------------------------  | | | | | | | | | | |
| | | | | | | | | | |         \   ^__^                                             | | | | | | | | | | |
| | | | | | | | | | |          \  (oo)\_______                                     | | | | | | | | | | |
| | | | | | | | | | |             (__)\       )\/\                                 | | | | | | | | | | |
| | | | | | | | | | |                 ||----w |                                    | | | | | | | | | | |
| | | | | | | | | | \                 ||     ||                                    / | | | | | | | | | |
| | | | | | | | | |  --------------------------------------------------------------  | | | | | | | | | |
| | | | | | | | | |         \   ^__^                                                 | | | | | | | | | |
| | | | | | | | | |          \  (oo)\_______                                         | | | | | | | | | |
| | | | | | | | | |             (__)\       )\/\                                     | | | | | | | | | |
| | | | | | | | | |                 ||----w |                                        | | | | | | | | | |
| | | | | | | | | \                 ||     ||                                        / | | | | | | | | |
| | | | | | | | |  ------------------------------------------------------------------  | | | | | | | | |
| | | | | | | | |         \   ^__^                                                     | | | | | | | | |
| | | | | | | | |          \  (oo)\_______                                             | | | | | | | | |
| | | | | | | | |             (__)\       )\/\                                         | | | | | | | | |
| | | | | | | | |                 ||----w |                                            | | | | | | | | |
| | | | | | | | \                 ||     ||                                            / | | | | | | | |
| | | | | | | |  ----------------------------------------------------------------------  | | | | | | | |
| | | | | | | |         \   ^__^                                                         | | | | | | | |
| | | | | | | |          \  (oo)\_______                                                 | | | | | | | |
| | | | | | | |             (__)\       )\/\                                             | | | | | | | |
| | | | | | | |                 ||----w |                                                | | | | | | | |
| | | | | | | \                 ||     ||                                                / | | | | | | |
| | | | | | |  --------------------------------------------------------------------------  | | | | | | |
| | | | | | |         \   ^__^                                                             | | | | | | |
| | | | | | |          \  (oo)\_______                                                     | | | | | | |
| | | | | | |             (__)\       )\/\                                                 | | | | | | |
| | | | | | |                 ||----w |                                                    | | | | | | |
| | | | | | \                 ||     ||                                                    / | | | | | |
| | | | | |  ------------------------------------------------------------------------------  | | | | | |
| | | | | |         \   ^__^                                                                 | | | | | |
| | | | | |          \  (oo)\_______                                                         | | | | | |
| | | | | |             (__)\       )\/\                                                     | | | | | |
| | | | | |                 ||----w |                                                        | | | | | |
| | | | | \                 ||     ||                                                        / | | | | |
| | | | |  ----------------------------------------------------------------------------------  | | | | |
| | | | |         \   ^__^                                                                     | | | | |
| | | | |          \  (oo)\_______                                                             | | | | |
| | | | |             (__)\       )\/\                                                         | | | | |
| | | | |                 ||----w |                                                            | | | | |
| | | | \                 ||     ||                                                            / | | | |
| | | |  --------------------------------------------------------------------------------------  | | | |
| | | |         \   ^__^                                                                         | | | |
| | | |          \  (oo)\_______                                                                 | | | |
| | | |             (__)\       )\/\                                                             | | | |
| | | |                 ||----w |                                                                | | | |
| | | \                 ||     ||                                                                / | | |
| | |  ------------------------------------------------------------------------------------------  | | |
| | |         \   ^__^                                                                             | | |
| | |          \  (oo)\_______                                                                     | | |
| | |             (__)\       )\/\                                                                 | | |
| | |                 ||----w |                                                                    | | |
| | \                 ||     ||                                                                    / | |
| |  ----------------------------------------------------------------------------------------------  | |
| |         \   ^__^                                                                                 | |
| |          \  (oo)\_______                                                                         | |
| |             (__)\       )\/\                                                                     | |
| |                 ||----w |                                                                        | |
| \                 ||     ||                                                                        / |
|  --------------------------------------------------------------------------------------------------  |
|         \   ^__^                                                                                     |
|          \  (oo)\_______                                                                             |
|             (__)\       )\/\                                                                         |
|                 ||----w |                                                                            |
\                 ||     ||                                                                            /
 ------------------------------------------------------------------------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
[1]cowsay is a Unix command-line program which can be installed by you package manager. The -n argument stops cowsay from doing word-wrapping, which destroys your recursive cow construct.

Comments !