[libvirt] [PATCH] schematestutils.sh: improve shell portability: avoid "echo -e"
Jim Meyering
jim at meyering.net
Wed Apr 14 12:20:39 UTC 2010
Daniel Veillard wrote:
> On Wed, Apr 14, 2010 at 01:28:54PM +0200, Jim Meyering wrote:
>> echo -e is not portable.
>> This is the sole remaining use in all of libvirt.
>>
>> >From a58cf340b5ebbca2157f43c6f23d4d6f56b848c7 Mon Sep 17 00:00:00 2001
>> From: Jim Meyering <meyering at redhat.com>
>> Date: Wed, 14 Apr 2010 13:25:46 +0200
>> Subject: [PATCH] schematestutils.sh: improve shell portability: avoid "echo -e"
>>
>> * tests/schematestutils.sh: Use printf rather than echo -e.
>> ---
>> tests/schematestutils.sh | 2 +-
>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/tests/schematestutils.sh b/tests/schematestutils.sh
>> index f172857..f2b3b50 100644
>> --- a/tests/schematestutils.sh
>> +++ b/tests/schematestutils.sh
>> @@ -22,7 +22,7 @@ do
>>
>> test_result $n $(basename $(dirname $xml))"/"$(basename $xml) $ret
>> if test "$verbose" = "1" && test $ret != 0 ; then
>> - echo -e "$cmd\n$result"
>> + printf '%s\n' "$cmd" "$result"
>> fi
>> if test "$ret" != 0 ; then
>> f=`expr $f + 1`
>
> I fail to see how printf(1) is any more portable than echo which
> is usually from the shell itself. Sounds to me that
> echo "$cmd" ; echo "$result"
> does what we want directly or am I mistaken ?
printf is most definitely more portable than "echo -e".
Note that printf has been a shell built-in in just about every
shell in common use for at least 10 years.
Documentation everywhere has been telling developers to prefer
"printf" over "echo-with-any-options" for nearly 20 years.
Here's an excerpt from "info coreutils echo":
POSIX does not require support for any options, and says that the
behavior of `echo' is implementation-defined if any STRING contains a
backslash or if the first argument is `-n'. Portable programs can use
the `printf' command if they need to omit trailing newlines or output
control characters or backslashes. *Note printf invocation::.
While my objection was to "echo -e", plain 'echo "$var"'
(where $var may be arbitrary) is not terribly reliable.
There are plenty of caveats when using plain "echo".
I.e., the first argument must not start with a "-".
Using printf the way I do above, even if $cmd or $value starts with "-"
or contains backslashes, it will be faithfully reproduced.
However, if you use your pair of "echo" commands
and some $result starts with "-", you'll get misleading output.
Here's the section on "echo" in autoconf's "Limitations of Builtins" section:
`echo'
The simple `echo' is probably the most surprising source of
portability troubles. It is not possible to use `echo' portably
unless both options and escape sequences are omitted. Don't
expect any option.
Do not use backslashes in the arguments, as there is no consensus
on their handling. For `echo '\n' | wc -l', the `sh' of Solaris
outputs 2, but Bash and Zsh (in `sh' emulation mode) output 1.
The problem is truly `echo': all the shells understand `'\n'' as
the string composed of a backslash and an `n'. Within a command
substitution, `echo 'string\c'' will mess up the internal state of
ksh88 on AIX 6.1 so that it will print the first character `s'
only, followed by a newline, and then entirely drop the output of
the next echo in a command substitution.
Because of these problems, do not pass a string containing
arbitrary characters to `echo'. For example, `echo "$foo"' is safe
only if you know that FOO's value cannot contain backslashes and
cannot start with `-'.
If this may not be true, `printf' is in general safer and easier
to use than `echo' and `echo -n'. Thus, scripts where portability
is not a major concern should use `printf '%s\n'' whenever `echo'
could fail, and similarly use `printf %s' instead of `echo -n'.
For portable shell scripts, instead, it is suggested to use a
here-document like this:
cat <<EOF
$foo
EOF
Alternatively, M4sh provides `AS_ECHO' and `AS_ECHO_N' macros
which choose between various portable implementations: `echo' or
`print' where they work, `printf' if it is available, or else
other creative tricks in order to work around the above problems.
More information about the libvir-list
mailing list