34

I, in my script, shell a function that prints a message on the console. It can be called from any other function.

function print_message
{
    echo "message content"
}

The problem is, in shell, functions like echo or printf that usually print data on standard output redirect their messages to the calling function instead as a return value.

return_value=$(print_message) # this line print nothing.
echo $return_value # This line print the message. I don't want to have to do it.

I would like to avoid this behavior and print it directly on standard - or error - output. Is there a way to do it?

Or am I just wrong to want to use functions in shell, and should I use instead a huge script to handle any comportment?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aracthor
  • 5,757
  • 6
  • 31
  • 59
  • 3
    You want the output from `print_message` to go to standard error? Always? Redirect in the function then `echo "message content" >&2`. – Etan Reisner Jul 27 '15 at 15:08
  • @EtanReisner - Sounds like they want it on standard out *and* standard error. STDOUT so it's captured by `$( ... )` and STDERR so it shows up on screen. – Mr. Llama Jul 27 '15 at 15:12
  • @EtanReisner That works for standard error, but is there a way to print it to standard output ? `>&1` doesn't seems to work. – Aracthor Jul 27 '15 at 15:12
  • 3
    The `$(...)` syntax is *capturing* standard output. That's where your problem is coming from in the first place. That's what it does. You can't have your function output to some *other* standard output than the rest of whatever you are calling in the `$(...)` context other than to use standard error and/or detect and print to the tty/etc. directly. – Etan Reisner Jul 27 '15 at 15:14

3 Answers3

47

The $(...) calling syntax captures standard output. That is its job. That's what it does.

If you want static messages that don't get caught by that then you can use standard error (though don't do this for things that aren't error message or debugging messages, etc. please).

You can't have a function which outputs to standard output but that doesn't get caught by the $(...) context it is running in because there's only one standard output stream. The best you could do for that would be to detect when you have a controlling terminal/etc. and write directly to that instead (but I'd advise not doing that most of the time either).

To redirect to standard error for the function entirely you can do either of these.

print_message() {
    echo "message content" >&2
}

or

print_message() {
    echo "message content"
} >&2

The difference is immaterial when there is only one line of output but if there are multiple lines of output then the latter is likely to be slightly more optimized (especially when the output stream happens to be a file).

Also avoid the function keyword as it isn't POSIX/spec and isn't as broadly portable.

Etan Reisner
  • 77,877
  • 8
  • 106
  • 148
3

You are explicitly saying "don't print the output directly! Put it in a variable so I can print it myself!".

You can simply stop doing that, and the message will be printed automatically:

$ cat yourscript 
#!/bin/bash

function print_message
{
    echo "message content"
}

print_message

$ ./yourscript
message content
that other guy
  • 116,971
  • 11
  • 170
  • 194
-3

Invoking print_message inside $(...) redirects the output. If you don't want the output redirected then invoke the command without the $(...). E.g.

 return_value=print_message # this line print nothing.
 echo $return_value # this line print the message. I don't want to have to do it.

Note, the return value from the function you provided will now be the name of the function.

cacciatc
  • 9
  • 5
  • 4
    This doesn't invoke `print_message` at all. This will print `print_message` as a result of the `echo` line. – Etan Reisner Jul 27 '15 at 15:23
  • It works for me and what I am reading online says you only need to enter the name of the function to invoke it. For example, `function print_message { echo "message content" } print_message print_message` Prints the output twice. – cacciatc Jul 27 '15 at 15:33
  • 3
    It cannot be working for you. Try it again and make sure your function outputs something *other* than `print_message`. Yes, the name by itself is enough to call a function in a location where that happens but `return_value=print_message` is **not** a location where that happens. See http://ideone.com/dnEvPA – Etan Reisner Jul 27 '15 at 15:41