Bash – Redirect all standard out for rest of script

bashio-redirectionshell

I have a bash script that I want to redirect all the rest of the output into a file.

#!/bin/bash
# the part I don't know  ${file}
echo spo 
echo car

cat ${file}

output should be spo\ncar\n

Best Answer

If you redirect stdout for the rest of the script, then that would include the "cat" command, so you wouldn't see its output, $file could fill up indefinitely with recursive copies of itself (and would if it wouldn't be so small as to let cat see the end of it before starting to write to it).

To redirect stdout from now on, you simply do:

exec > "$file"

But here maybe you want:

#! /bin/bash -
{
  echo spo 
  echo car
} > "$file"

cat < "$file"

You can also do things like:

exec 3>&1 # save stdout as fd 3
exec > "$file"
echo spo
echo car
exec >&3 3>&- # restore stdout and close fd 3
cat < "$file"

(and by the way, the above is what modern shells do internally when you redirect a compound command like { some; code; } > ... (though they use a fd above 10 and set the O_CLOEXEC flag on it so that executed commands don't see it), while the Bourne shell would fork a subshell in that case)

Also note that in the code above, you don't have to restore stdout for the rest of the script, you can do it for the cat command only:

cat < "$file" >&3 3>&-

(the 3>&- (closing fd 3) is not necessary as cat doesn't use its fd 3 anyway but is good practice in the general case, and strictly speaking, we'd have to add it to every command to emulate the O_CLOEXEC behavior of the shell).