74

What is the difference between the printf function in bash and the echo function?

Specifically, running:

echo "blah" >/dev/udp/localhost/8125

did not send the "blah" command to the server listening on 8125, whereas

printf "blah" >/dev/udp/localhost/8125

sent the data. Does printf send an extra EOF at the end of its output?

Kevin Burke
  • 1,971
  • 10
    Given that it is UDP, did you make sure to repeat your above experiments several times? The only difference between echo "blah" and printf "blah" is echo will output an extra newline. Does that matter to the server? Does the order when receiving several commands in a row matter? EOF is not something you send or even a character - it's a condition you receive when there is nothing left to read. – jw013 Dec 12 '12 at 19:11
  • 2
    How did you verify that the echo-attempt does not send the string to the server? The proper way would be to monitor lo and not rely on the server printing stuff. There is always iptables ... – Bananguin Dec 12 '12 at 21:44

6 Answers6

80

Both echo and printf are built-in commands (printf is Bash built-in since v2.0.2, 1998). echo always exits with a 0 status, and simply prints arguments followed by an end of line character on the standard output, while printf allows for definition of a formatting string and gives a non-zero exit status code upon failure.

printf has more control over the output format. It can be used to specify the field width to use for item, as well as various formatting choices for numbers (such as what output base to use, whether to print an exponent, whether to print a sign, and how many digits to print after the decimal point). This is done by supplying the format string, that controls how and where to print the other arguments and has the same syntax as C language (%03d, %e, %+d,...). This means that you must escape the percent symbol when not talking about format (%%).

Probably, if you add the newline character that echo uses by default (except when using -n option) you'll get the same effect.

printf "blah\n" >/dev/udp/localhost/8125

Concerning performance, I always had in mind that echo was faster than printf because the latter has to read the string and format it. But testing them with time (also built-in) the results say otherwise:

$ time for i in {1..999999}; do echo "$i" >/dev/null; done
real    0m10.191s
user    0m4.940s
sys 0m1.710s

$ time for i in {1..999999}; do printf "$i" >/dev/null; done real 0m9.073s user 0m4.690s sys 0m1.310s

Telling printf to add newline characters, just as echo does by default:

$ time for i in {1..999999}; do printf "$i\n" >/dev/null; done
real    0m8.940s
user    0m4.230s
sys 0m1.460s

that is obviously slower than without printing the \n, but yet faster than echo.

thanasisp
  • 8,122
J. A. Corbal
  • 1,757
33

The difference is that echo sends a newline at the end of its output. There is no way to "send" an EOF.

9

Here is probably the best description of echo vs printf

http://www.in-ulm.de/~mascheck/various/echo+printf/

At a very high level.. printf is like echo but more formatting can be done.

Mike
  • 642
  • 4
    Good reference, but not really an answer to the question, nor an explanation why printf works and echo doesn't. – gertvdijk Dec 12 '12 at 16:39
9

echo prints its argument followed by a newline. With multiple arguments, they are separated by spaces. Depending on the unix variant, the shell and the shell options, it may also interpret some escape sequences beginning with \, and it may treat the first argument(s) as options if they start with -.

printf interprets its first argument as a format, and subsequent arguments as arguments to the % specifiers. No newline is added unless you specify one. In the first argument, all characters except two are interpreted literally: % starts a printf specifier, and \ starts an escape sequence (e.g. \n for a newline character).

Because different shells work differently, echo "$string" does not always print the specified string plus a newline. A reliable way of printing a string is printf %s "$string". If you want a newline after the string, write printf '%s\n' "$string".

In your case, assuming that blah doesn't start with a - or contain % or \, the only difference between the two commands is that echo adds a newline and printf doesn't.

  • 6
    Note that printf will also treat leading arguments that start with - as options, though contrary to echo, you can use -- to mark the end of options as in printf -- '--%s--\n' foo bar – Stéphane Chazelas Oct 20 '16 at 15:29
5

If you want to literally print the string "-e", you will have difficulties doing it with echo. I faced such a problem recently while writing a script.

I had to use prinf to be able to print the literal string "-e".

4

For trivial messages (no escape sequences, no options), echo is fine. As soon as you need something more complex, you shoud use printf which is portable (i.e. behave the same regardless of the OS) and allows much better formatting, being designed from the same name C function.

Should you want to call echo in your example, the correct way would be either:

echo -n "blah" >/dev/udp/localhost/8125

or

echo "blah\c" >/dev/udp/localhost/8125

depending on the echo implementation you use.

jlliagre
  • 61,204