[Chapter 46] 46.10 A Portable echo Command
Author: Jerry Peek, Tim O'Reilly & Mike Loukides
Date: 1998-08-04T21:55:48Z

#

| Chapter 46 Shell Script Debugging and Gotchas |

## 46.10 A Portable echo Command

One of the frustrating changes to UNIX (for me, at least) is the newer versions of echo (8.6) that interpret escape sequences like `\c` and `\007`. That feature is actually nice to have - usually, at least. But if the shell script has to work on both Berkeley and System V UNIX, it's a headache to write an echo command that prompts a user for an answer - with no newline at the end of the line. (bash users have a better - though less portable - answer: the -e and -E options explained at the end of the article.) With the original UNIX echo command, you write:

>     echo -n "Answer y for yes or n for no: "

but the newer echo needs:

>     echo "Answer y for yes or n for no: \c"

and giving the wrong command to the wrong echo makes messy output.

I've seen workarounds by Bruce Barnett and Liam R. E. Quin. I've turned them into this version. It sets shell variables that you use this way:

>     $echo "Answer y for yes or n for no: ${nnl}"

Can your shell script be set up for a particular UNIX version ahead of time? If it can, write your no - newline echo commands like the example above - and put the lines below at the top of your script:

>     # UN-COMMENT THE LINE FOR YOUR SYSTEM:
>     echo="echo -n"   nnl= ;;                                     # BSD
>     #echo="echo"      nnl="\c" ;;                                # Sys V
>     #echo="echo -n"   nnl=     PATH=/usr/bin:$PATH; export PATH  # SunOS

Lines similar to those let the person who installs the script set the right echo version.

But if your script is shared between many UNIX systems (across a networked filesystem) or runs on a system where users can choose BSD or System V features (like SunOS), your script will need to configure echo each time it runs. To do that, put the following code at the top of your script:

>     case "`echo 'x\c'`" in
>     'x\c')  echo="echo -n"   nnl= ;;       # BSD
>     x)      echo="echo"      nnl="\c" ;;   # Sys V
>     *)      echo "$0 quitting: Can't set up echo." 1>&2; exit 1 ;;
>     esac

In that code, the shell runs the current echo command and tests its output. Newer echo commands will interpret the `\c` and print `x` (with no newline after it; that doesn't matter here). Berkeley echo commands will echo the `\c` literally; this is matched by the first pattern instead.

You can handle other escape sequences and unprintable characters in the same way. For example, to make the code set `$esc`, a shell variable that makes an ESCape character, you can add lines like one of the two below:

    `echo...\033`
    esc=`echo -n d | tr "d" "\033"`     # BSDesc="\033"                          # Sys V

If you use bash, you can tell its echo command which way to act. The echo -e command always does backslash-escape interpretation. The echo -E command never interprets backslashes. And the option -n (no newline) works in both cases.

- JP

46.9 If Command Doesn't Return a Status, Test the Error Messages |  | 47. C Shell Programming...NOT