Zombo
Zombo

Reputation: 1

Redirect stdout and stdin to file

I can write to and read from a file:

echo a > b.txt
read c < b.txt

Is Bash able to do this implicitly? Something like:

<turn on implicit mode>
echo a
read c
<turn off implicit mode>

While “implicit mode” is on, all stdout goes to b.txt and all stdin reads from b.txt. I tried:

exec > b.txt

but it only affects stdout.

Upvotes: 0

Views: 1572

Answers (4)

Paul
Paul

Reputation: 605

In my case I have a client/server that communicates via stdin/stdout, and I wanted to capture those streams. Here's the bash script:

cat - | tee stdin.log | $cmd | tee stdout.log

Upvotes: 0

Zombo
Zombo

Reputation: 1

Working off the responses here, I came up with this:

d=`tty`
exec >b.txt <b.txt
echo a
read c
exec >$d <$d

I also realized that it might be better to leave stdout and stdin alone:

exec 3>b.txt 4<b.txt
echo a >&3
read c <&4

Upvotes: -1

Barmar
Barmar

Reputation: 780698

You can use exec to redirect both stdin and stdout at the same time

exec > b.txt < b.txt
echo a
read c

I wasn't sure if this would read what it wrote, but I tested it and it works.

You can revert it by duping the original FDs in other FDs, and then restoring them when you're done.

exec 10<&0 11>&1 > b.txt < b.txt
echo a
read c
exec <&10 10<&- >&11 11>&-
echo $c

Upvotes: 5

Jeff Bowman
Jeff Bowman

Reputation: 95614

There is no way to get bash to assume this behavior, particularly given that b.txt is the input of one command and the output of another. There are a number of solutions to similar problems, that may be applicable depending on your actual problem:

  1. Assuming you mean in a script and not in interactive mode, you can redirect a group of commands using braces, which saves you from having to spell everything out. It won't work if you're trying to make b.txt both the source and the destination within the group of commands.

    {
      echo a
      read c
    } <b_in.txt >b_out.txt
    
  2. If the fact that b.txt exists isn't important, you can just use a pipe, or a pipe with tee:

    echo a | read c
    echo a | tee b.txt | read c
    
  3. If you need b.txt because it behaves as a file, you can also consider process substitution.

    command_that_takes_a_file <(echo a)
    command_that_takes_stdin < <(echo a)
    

Upvotes: 0

Related Questions