The solution you are showing above is one that is general purpose and covers a lot of cases. Unless you know you have an issue, you may want to adopt a YAGNI (You Ain't Gonna Need It) posture and just redirect your selected lines to /dev/tty.
If you want to avoid that, then you need to understand the file descriptor (fd) juggling that is going on.
The 3>&1
is copying the calling context's stdout to a "holding cell" so that the function can output to whatever the calling context's stdout is. In this case, it is /dev/tty. Remember, the function will be called with stdout belonging to a subshell for the ${} substitution.
The exec 4>&1
creates a copy of fd1, which is the stdout of the function. fd4 is being used as a holding cell for the stdout the function starts with. The >&3
is setting the function/subshell's stdout to the caller's stdout. Thus, all output will go to the caller's stdoout. UNTIL, the end where the >&4-
moves the saved stdout back to where it started, allowing the last echo "$s"
to be in the function(and subshell)'s stdout.
Whew!
The >&3
and >&4-
could also be written more clearly as 1>&3
and 1>&4-
.
The bash
manual section on REDIRECTION, explains all the gory & nomenclature. I was pleased and surprised to see that it is actually possible to use {name} forms to change the numbers to words.
"Each redirection that may be preceded by a file descriptor number may instead be preceded by a word of the form {varname}. In this case, for each redirection operator except >&- and <&-, the shell will allocate a file descriptor greater than 10 and assign it to varname. If >&- or <&- is preceded by {varname}, the value of varname defines the file descriptor to close."
I didn't test this, but it suggests that you could code this as:
#!/bin/bash
exec {caller_stdio}>&1
returnString() {
exec {func_stdio}>&1 1>&{caller_stdio}
local s=$1
s=${s:="some default string"}
echo "writing to stdout"
echo "writing to stderr" >&2
exec 1>&{func_stdio}-
echo "$s"
}
my_string=$(returnString "$*")
echo "my_string: [$my_string]"
stdin
,stdout
andstderr
. Here is my favorite tutorial, if you wanna call it that. http://wiki.bash-hackers.org/howto/redirection_tutorial