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?

  • 11
    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
    Commented Dec 12, 2012 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
    Commented Dec 12, 2012 at 21:44

6 Answers 6


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.

  • 10
    printf has been a bash builtin since 2.0.2 (1998), not 4.1 (the .7 would identify a bug-fix patch, so can't introduce a new feature). Commented Oct 28, 2015 at 21:29
  • 9
    echo can return a non-zero exit status if it fails to write its output. Commented Oct 28, 2015 at 21:34
  • 4
    Couldn't verify the performance tests. These gave me the contrary results. echo is faster on my side (bash 4.3.46). :-/
    – wget
    Commented Oct 25, 2016 at 13:42
  • Same thing, echo is faster (GNU bash, version 4.3.33(1)-release)
    – Peter
    Commented May 8, 2017 at 20:19
  • 1
    Repeated the results with GNU bash 4.4.12(1), and I've got different results: printf: real 0m8.759s/user 0.6719s | echo: real 0m8.463/user 0.6.406s. It's strange. Commented Jun 7, 2017 at 14:46

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

  • 64
    There are more differences than that.
    – jlliagre
    Commented Dec 12, 2012 at 16:05
  • 6
    Although this answer does (lightly) explain why the first command and second command differ, which is really what Kevin is asking. Commented Dec 12, 2012 at 18:19

Here is probably the best description of echo vs printf


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

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

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 Commented Oct 20, 2016 at 15:29

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".


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


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

depending on the echo implementation you use.

Not the answer you're looking for? Browse other questions tagged .