2010-06-07 14:36:16 8 Comments

Is there a standard Bash tool that acts like echo but outputs to stderr rather than stdout?

I know I can do echo foo 1>&2 but it's kinda ugly and, I suspect, error prone (e.g. more likely to get edited wrong when things change).


@Polymerase 2020-06-06 17:20:18

Combining solution suggested by James Roth and Glenn Jackman

  • add ANSI color code to display the error message in red:
echoerr() { printf "\e[31;1m%s\e[0m\n" "$*" >&2; }

# if somehow \e is not working on your terminal, use \u001b instead
# echoerr() { printf "\u001b[31;1m%s\u001b[0m\n" "$*" >&2; }

echoerr "This error message should be RED"

@Sebastian 2017-09-03 01:48:32

My suggestion:

echo "my errz" >> /proc/self/fd/2


echo "my errz" >> /dev/stderr

echo "my errz" > /proc/self/fd/2 will effectively output to stderr because /proc/self is a link to the current process, and /proc/self/fd holds the process opened file descriptors, and then, 0, 1, and 2 stand for stdin, stdout and stderr respectively.

The /proc/self link doesn't work on MacOS, however, /proc/self/fd/* is available on Termux on Android, but not /dev/stderr. How to detect the OS from a Bash script? can help if you need to make your script more portable by determining which variant to use.

@MarkHu 2017-11-22 00:30:25

The /proc/self link doesn't work on MacOS, so I'll stick with the more straight-forward /dev/stderr method. Also, as noted in other answers/comments, it is probably better to use >> to append.

@go2null 2018-02-01 11:30:49

/proc/self/fd/* is available on Termux on Android, but not /dev/stderr.

@Marco Aurelio 2014-05-08 18:59:47

You could do this, which facilitates reading:

>&2 echo "error"

>&2 copies file descriptor #2 to file descriptor #1. Therefore, after this redirection is performed, both file descriptors will refer to the same file: the one file descriptor #2 was originally referring to. For more information see the Bash Hackers Illustrated Redirection Tutorial.

@Marco Aurelio 2014-10-03 06:45:48

I learn this trick quite a while ago. This page has some good information to it.

@Braden Best 2015-07-13 21:52:17

@BCS I dunno about using an alias in a shell script. It would probably be safer to use errcho(){ >&2 echo [email protected]; }

@Iskren Ivov Chernev 2015-09-08 23:59:49

>&2 is normally put at the end. This will work, but its used less often

@Hephaestus 2015-11-05 15:07:35

In the nearly 40 years that I've been using Unix-like systems it has never occurred to me that you could put the redirect anywhere but at the end. Putting it up front like this makes it much more obvious (or "facilitates reading" as @MarcoAurelio says). +1 for teaching me something new.

@Jon Red 2020-03-13 18:05:36

FYI: if you want to format or do anything besides simply echo the string then you'll have to move the redirect back to the end. For example errcho(){ >&2 echo [email protected]|pr -To5;} won't work. To do something like that you'll have to put the redirect somewhere after the last pipe like: errcho(){ echo [email protected]|>&2 pr -To5;}

@Xavi Montero 2020-06-18 18:19:11

Bravo for the Bash Hackers Illustrated Redirection Tutorial pointer!

@GuyPaddock 2019-02-18 00:17:35

Another option that I recently stumbled on is this:

        echo "First error line"
        echo "Second error line"
        echo "Third error line"
    } >&2

This uses only Bash built-ins while making multi-line error output less error prone (since you don't have to remember to add &>2 to every line).

@return42 2019-02-20 08:33:19

Can't believe it, you vote me down when I recommend to use bash-redirect and in your own answer you are using bash-redirect.

@GuyPaddock 2019-11-27 19:09:19

@return42 I voted your answer down because all it did was tell the OP that there's no better answer than what they started with.. it's not really an answer. I also don't see a sub-shell suggestion in your answer... your answer really just advises the OP not to use cat or any other utility, which is off-topic for the question.

@return42 2019-11-28 20:13:33

@Steven Penny 2013-01-16 03:57:04

Another option

echo foo >>/dev/stderr

@Dacav 2014-02-17 16:26:40

Is this option portable? Do someone know if this is not working for some unix flavour?

@Zachary Vance 2014-04-28 22:35:17

It doesn't work in certain chroots, which can't access /dev/stderr.

@doshea 2014-09-06 23:25:45

If the script that executes this line - let's call it foo - has its own stderr redirected - e.g. foo >foo.log 2>&1 - then echo foo >/dev/stderr will clobber all the output before it. >> should be used instead: echo foo >>/dev/stderr

@jbruni 2016-04-28 00:08:45

Similarly, you have /dev/fd/2.

@Sebastian 2017-09-03 01:51:06

@Dacav this is for sure portable: /proc/self/fd/2. See my answer below :)

@Cezary Baginski 2016-03-18 18:07:43

Note: I'm answering the post- not the misleading/vague "echo that outputs to stderr" question (already answered by OP).

Use a function to show the intention and source the implementation you want. E.g.


[ -x error_handling ] && . error_handling

config_error $filename "invalid value!"

output_xml_error "No such account"

debug_output "Skipping cache"

log_error "Timeout downloading archive"

notify_admin "Out of disk space!"

fatal "failed to open logger!"

And error_handling being:

[email protected]

config_error() { filename="$1"; shift; echo "Config error in $filename: $*" 2>&1; }

output_xml_error() { echo "<error>$*</error>" 2>&1; }

debug_output() { [ "$DEBUG"=="1" ] && echo "DEBUG: $*"; }

log_error() { logger -s "$*"; }

fatal() { which logger >/dev/null && logger -s "FATAL: $*" || echo "FATAL: $*"; exit 100; }

notify_admin() { echo "$*" | mail -s "Error from script" "$ADMIN_EMAIL"; }

Reasons that handle concerns in OP:

  • nicest syntax possible (meaningful words instead of ugly symbols)
  • harder to make an error (especially if you reuse the script)
  • it's not a standard Bash tool, but it can be a standard shell library for you or your company/organization

Other reasons:

  • clarity - shows intention to other maintainers
  • speed - functions are faster than shell scripts
  • reusability - a function can call another function
  • configurability - no need to edit original script
  • debugging - easier to find the line responsible for an error (especially if you're deadling with a ton of redirecting/filtering output)
  • robustness - if a function is missing and you can't edit the script, you can fall back to using external tool with the same name (e.g. log_error can be aliased to logger on Linux)
  • switching implementations - you can switch to external tools by removing the "x" attribute of the library
  • output agnostic - you no longer have to care if it goes to STDERR or elsewhere
  • personalizing - you can configure behavior with environment variables

@James Roth 2010-06-07 14:52:56

You could define a function:

echoerr() { echo "[email protected]" 1>&2; }
echoerr hello world

This would be faster than a script and have no dependencies.

Camilo Martin's bash specific suggestion uses a "here string" and will print anything you pass to it, including arguments (-n) that echo would normally swallow:

echoerr() { cat <<< "[email protected]" 1>&2; }

Glenn Jackman's solution also avoids the argument swallowing problem:

echoerr() { printf "%s\n" "$*" >&2; }

@Camilo Martin 2014-06-24 13:23:12

I must say that echo is kinda unreliable. echoerr -ne xt is not going to print "-ne xt". Better use printf for that.

@Camilo Martin 2014-06-24 13:26:49

Oh, you can actually use cat too: echoerr() { cat <<< "[email protected]" 1>&2; }

@James Roth 2014-06-24 13:47:12

I wasn't aware of that. Added.

@Avindra Goolcharan 2015-03-11 19:39:18

and do an export -f echoerr if you want any subshells to pick up the function

@glenn jackman 2016-03-13 16:34:41

Or, printf "%s\n" "$*" >&2

@GKFX 2016-09-22 19:01:19

@CamiloMartin cat <<< "[email protected]" is even worse; it condenses all spaces between arguments into one, so you have to quote what you pass to it for reliability.

@Camilo Martin 2016-09-29 12:49:22

@GKFX no it doesn't, echoerr 'foo ​ bar' will have two spaces between foo and bar. (I had to add a zero-width joiner to make it show two spaces in this comment, so don't copy and paste it or it will be three spaces in the console).

@GKFX 2016-09-29 13:20:27

@CamiloMartin Putting the double space in quotes (or escaping it etc.) works fine, but the first code block in this answer didn't have quotes. I meant echoerr a ​ b. However, I've just checked and the real echo command behaves the same as yours so clearly this is not a bug.

@Camilo Martin 2016-09-29 19:56:09

@GKFX Of course it only works correctly when quoting. Why people don't quote their strings is beyond me. (when you don't quote, everything separated by one or more $IFS whitespace is sent as a separate argument, which in the case of echo means concatenating them with 0x20s, but the dangers of not quoting far outweight the convenience of 2 less characters to type).

@GKFX 2016-09-30 17:52:29

@CamiloMartin I see that now; I got used to the unquoted form from seeing it so much and never realised the pitfalls.

@Camilo Martin 2016-10-01 20:59:52

@GKFX It's a common mistake (unfortunately). On that regard, remember to use single-quotes when you don't want anything to be interpreted (not just $variables, but consider as well echo "why!?" vs echo 'why!?', also note how echo '\' is correct). Bash is beautiful once you remember those things by heart, but it is held back by misunderstandings of its peculiarities and the bugs they cause (the same thing that happens with Javascript, which came a long way but is still shunned by people who got stuck with the bad first impression).

@VasiliNovikov 2018-05-17 07:47:13

Makes sense to erase the unsafe answer ([email protected]), and only leave out the two last correct ones.

@ardnew 2020-04-03 02:15:44

you can still use echo (and not consume leading switches) with something like echoerr() { echo $'\033' [email protected] 1>&2; } or maybe echoerr() { echo $' \010'[email protected] 1>&2; }. these will appear as expected when printed to the terminal, but those escaped chars do get output, even if you don't see them

@Noah Sussman 2016-02-19 23:48:42

Mac OS X: I tried the accepted answer and a couple of other answers and all of them resulted in writing STDOUT not STDERR on my Mac.

Here is a portable way to write to standard error using Perl:

echo WARNING! | perl -ne 'print STDERR'

@Noah Sussman 2016-08-02 00:51:30

lol downvote all you want but this is the solution I actually use in my code!

@return42 2014-10-09 13:18:17

Don't use cat as some are mentioned here. cat is a program while echo and printf are bash (shell) builtins. Launching a program or an other script (also mentioned above) means create an new process with all it's costs. Using builtins, writing functions are quite cheap, because there is no need to create (execute) a process (-environment).

The opner asks "is there any standard tool to output (pipe) to stderr", the schort answer is : NO ... why? ... rediredcting pipes is an elemantary concept in systems like unix (Linux...) and bash (sh) builds up on these concepts.

I agree with the opener that redirecting with notations like this: &2>1 is not very pleasant for modern programmers, but that's bash. Bash was not intended to write huge and robust programs, it is intended to help the admins to get there work with less keypresses ;-)

And at least, you can place the redirection anywhere in the line:

$ echo This message >&2 goes to stderr 
This message goes to stderr

@GuyPaddock 2019-02-18 00:01:36

Telling devs not to use programs only because of performance reason is premature optimization. Elegant, easy-to-follow approaches should preferred over hard-to-understand code that performs better (on the order of milliseconds).

@return42 2019-02-18 12:26:43

@GuyPaddock sorry, you haven't read through this properly. Firs; Its about redirecting pipes which is well handled by the bash. If one do not like the (ugly) syntax how bash redirects, he should stop implementing bash scripts or learn the bash way. Second; you should know how expensive it is to launch a new prozess compared to yust call a bash builtin.

@GuyPaddock 2019-02-18 21:56:31

There's a difference between letting someone know the performance trade-offs of Bash built-ins vs cat and instructing someone not to use cat because it's slow. There are countless use cases where cat is the right choice, so that's why I object to your answer.

@return42 2019-02-20 07:55:03

@GuyPaddock The opener asked for a echo replacement. Even if he use cat, he has to use a bash redirect. anyway. So, there is absolute no sense in to use cat here. BTW I use cat 100 times a day, but never in the context the opener asked for... you got it?

@Grzegorz Luczywo 2014-08-04 19:15:38

If you don't mind logging the message also to syslog, the not_so_ugly way is:

logger -s $msg

The -s option means: "Output the message to standard error as well as to the system log."

@code_monk 2016-07-28 12:39:39

this is great! how portable is it?

@miku 2019-05-20 16:52:01

@code_monk: The logger command is expected to be IEEE Std 1003.2 ("POSIX.2") compatible, The logger command is part of the util-linux package and is available from Linux Kernel Archive ⟨⟩.

@Brandon Rhodes 2012-07-10 21:24:56

Since 1 is the standard output, you do not have to explicitly name it in front of an output redirection like > but instead can simply type:

echo This message goes to stderr >&2

Since you seem to be worried that 1>&2 will be difficult for you to reliably type, the elimination of the redundant 1 might be a slight encouragement to you!

@Douglas Mayle 2013-01-24 00:16:00

read is a shell builtin command that prints to stderr, and can be used like echo without performing redirection tricks:

read -t 0.1 -p "This will be sent to stderr"

The -t 0.1 is a timeout that disables read's main functionality, storing one line of stdin into a variable.

@James Roth 2013-08-29 19:49:37

Bash on OS X doesn't allow the "0.1"

@erselbst 2012-02-03 08:40:43

This is a simple STDERR function, which redirect the pipe input to STDERR.

# *************************************************************
# This function redirect the pipe input to STDERR.
# @param stream
# @return string
function STDERR () {

cat - 1>&2


# remove the directory /bubu
if rm /bubu 2>/dev/null; then
    echo "Bubu is gone."
    echo "Has anyone seen Bubu?" | STDERR

# run the and redirect you output
[email protected]:~$ ./ >/tmp/bubu.log 2>/tmp/bubu.err

@BCS 2012-02-03 15:54:36

I think you can do the same thing with alias and be much more compact

@ardnew 2020-04-03 01:30:32

or you can just pipe to the device file directly echo what | /dev/stderr ...

@n0rd 2010-06-07 14:48:02

Make a script

echo $* 1>&2

that would be your tool.

Or make a function if you don't want to have a script in separate file.

@Cascabel 2010-06-07 14:59:10

Better for it to be a function (like James Roth's answer), and better to pass along all arguments, not just the first.

@Ogre Psalm33 2014-05-20 14:44:15

Why would a function be better? (Or, alternatively: "Better to explain why it would be better...")

@destenson 2015-12-01 03:52:03

@OgrePsalm33 One reason a function would be better is that when calling a script, usually a new shell instance is created to provide an environment in which to execute the script. A function, on the other hand, is placed into the currently running shell's environment. Calling a function, in this case, would be a much more efficient operation since the creation of another instance of a shell would be avoided.

@Matthew Flaschen 2010-06-07 14:37:10

No, that's the standard way to do it. It shouldn't cause errors.

@BCS 2010-06-07 14:42:33

It shouldn't cause errors, but I might be more likely to. OTOH it's not that big a deal.

@Mike DeSimone 2010-06-07 14:52:10

The only way it will fail is if the file ID for stdout is not 1 or the file ID for stderr is not 2. As these constants are defined by POSIX.1, which I believe is a prerequisite for bash to build, this will work for the forseeable future. Thus, I am curious as to what you mean by "likely to get edited wrong when things change". Are you having a similar problem with people changing the word "echo" into something else?

@Cascabel 2010-06-07 15:00:10

@Mike DeSimone: If someone else messes with the code, shuffles around the output, and doesn't actually know bash, they could easily drop (or mistype) the 1>&2. We all wish this wouldn't happen, but I'm sure we've all been places where it does.

@BCS 2010-06-07 17:15:25

( echo something 1>&2 ; something else ) > log -> (echo something; cp some junk 1>&2 ; something else) > log Oops.

@Mike DeSimone 2010-06-07 17:34:43

IMHO, if someone messes with the code and doesn't know bash, this may be the least of your problems.

@intuited 2010-06-07 23:19:12

I think if that's likely to be an issue, you should start using a different language: trying to make bash foolproof is a fool's venture.

Related Questions

Sponsored Content

7 Answered Questions

[SOLVED] How to redirect and append both stdout and stderr to a file with Bash?

30 Answered Questions

[SOLVED] How to change the output color of echo in Linux

6 Answered Questions

13 Answered Questions

[SOLVED] How to echo shell commands as they are executed

23 Answered Questions

[SOLVED] Echo newline in Bash prints literal \n

  • 2011-12-11 21:01:54
  • Sergey
  • 2169267 View
  • 2419 Score
  • 23 Answer
  • Tags:   bash echo newline

14 Answered Questions

[SOLVED] How do I set a variable to the output of a command in Bash?

11 Answered Questions

[SOLVED] How can I pipe stderr, and not stdout?

15 Answered Questions

[SOLVED] Redirect stderr and stdout in Bash

3 Answered Questions

[SOLVED] How do I redirect the output from a bash script to stderr

  • 2017-10-18 11:46:41
  • Phil O
  • 263 View
  • 1 Score
  • 3 Answer
  • Tags:   linux bash

Sponsored Content