24

Just like we redirect output from a for loop block to a file

for ()
do
  //do something
  //print logs
done >> output file

Similarly in shell script, is there a way to redirect output from a function block to a file, something like this?

function initialize {
         //do something
         //print something
} >> output file

//call initialize

If not, is there some other way I can achieve that? Please note my function has lot of messages to be printed in a log. Redirecting output to a file at every line would result in a lot of I/O utilization.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
dig_123
  • 2,240
  • 6
  • 35
  • 59

4 Answers4

19

Do the redirection when you are calling the function.

#!/bin/bash
initialize() {
  echo 'initializing'
  ...
}
#call the function with the redirection you want
initialize >> your_file.log

Alternatively, open a subshell in the function and redirect the subshell output:

#!/bin/bash
initialize() {
  (  # opening the subshell
    echo 'initializing'
    ...
  # closing and redirecting the subshell
  ) >> your_file.log
}
# call the function normally
initialize
Carlos Campderrós
  • 22,354
  • 11
  • 51
  • 57
  • 1
    I'm trying to do the same thing, and coded my function exactly like in the original question. `echo` statements exist in the function, and after the function's closing brace it redirects to stderr. It works, but I came to SO to verify that this was considered ok to do. What is the reasoning behind doing the redirection when calling the function, instead of having the function do it itself? – smeep Oct 05 '16 at 18:48
  • (responding to an old comment as it may be relevant to others searching) - @smeep - if the function redirected its own output then all callers would be forced to accept that redirection, if it just sends output the default way the caller can choose to accept the default or redirect elsewhere. Also the syntax queries in the question would not work (redirect at end of function block), you would have to redirect every output line (or add an inner function and redirect its output). – David Spillett Jun 29 '22 at 10:16
16

The way you suggest is actually perfectly valid. The Bash manual gives the function declaration syntax as follows (emphasis mine)1:

Functions are declared using this syntax:

name () compound-command [ redirections ]

or

function name [()] compound-command [ redirections ]

So this would be perfectly valid and replace the contents of outfile with the argument to myfunc:

myfunc() {
    printf '%s\n' "$1"
} > outfile

Or, to append to outfile:

myappendfunc() {
    printf '%s\n' "$1"
} >> outfile

However, even though you can put the name of your target file into a variable and redirect to that, like this:

fname=outfile

myfunc() { printf '%s\n' "$1"; } > "$fname"

I think think it's much clearer to do the redirection where you call the function – just like recommended in other answers. I just wanted to point out that you can have the redirection as part of the function declaration.


1And this is not a bashism: the POSIX Shell spec also allows redirections in the function definition command.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
3

You can use for exec for shell redirection not sure if it will work for functions

exec > output_file
function initialize {
  ...
}
initialize
shyam
  • 9,134
  • 4
  • 29
  • 44
0

My solution is wrap the function.

init_internal(){
  echo "this is init_internal with params: $@"
  echo "arg1 $1"
  echo "arg2 $2"
}

init() {
  local LOG_PATH=$1
  echo "LOG at: $LOG_PATH"
  init_internal "${@:2}" > ./$LOG_PATH 2>&1
}

init log.log a b c d

cat ./log.log

It outputs:

LOG at: log.log
this is init_internal with params: a b c d
arg1 a
arg2 b
LingSamuel
  • 496
  • 5
  • 10