0

In an attempt to further understand bash, I am trying to replicate some functionalities of it. Right now I am in the process to implementing the redirecting and pipeline features. To further understand each of these concepts, apart from reading the docs (redirections and pipelines), I have been trying some special cases, and I have come up with this case that I am struggling to understand:

bash-3.2$ echo test > file | tr -d t < file | wc > file ; cat file
       0       0       0

I would expect the output of the command to be 1 1 3, but instead it outputs 0 0 0. I have tried the same command in zsh and the output is what I expected, so it is seems that some of my assumptions are incorrect for bash. For easier reference, I will consider the command provided as cmd1 | cmd2 | cmd. This is what I thought that happened when executing the command:

  1. stdout of cmd1 is redirected to stdin of cmd2.
  2. stdout of cmd2 is redirected to stdin of cmd3.
  3. cmd1 is executed:
    1. file is created or truncated.
    2. stdout of echo test is redirected to file.
    3. The echo command is executed and "test" is saved to file.
  4. cmd2 is executed:
    1. stdin of tr -d t is redirected to file.
    2. The tr command is executed and the "test" read from file becomes "es" and is outputted to cmd3.
  5. cmd3 is executed:
    1. file is truncated.
    2. stdout of wc is redirected to file.
    3. The wc command is executed with "es" as input and "1 1 3" is saved to file.

Clearly some of my assumptions are wrong and I would greatly appreciate all the possible corrections to them.

I have also tried other commands such as:

bash-3.2$ echo test > file | tr -d t < file | wc >> file ; cat file
test
       1       1       3
bash-3.2$ echo test > file | tr -d t < file | wc > file2 ; cat file ; cat file2
test
       1       1       3

These tests lead me to believe that my assumptions are probably wrong in the order of execution of things or even in the moment that the truncation is happening. Whatever it is, I would gladly appreciate any explanation or further help.

2
  • 1
    Does this answer your question? In what order do piped commands run?
    – AdminBee
    Commented Jun 12, 2023 at 13:28
  • @AdminBee It partially answers it. I was also trying to understand the interaction of redirections combined pipes. Turns out that because of the response to that answer there is no real interaction, so it did clarify something. Thanks! Commented Jun 14, 2023 at 8:00

1 Answer 1

1

The commands in a pipeline run simultaneously, so reading and writing from/to the same file depends on how the processes happen to get scheduled.

In particular, in step 4.2, there's no guarantee the file contains any data when tr starts reading from it as a) the echo on the left-hand side may not have written anything yet, and b) the redirection in wc > file may have truncated the file after echo had written it.

I'm not sure why you're using that first pipe there anyway, since the redirections to/from the file override the pipe. What you're doing there is pretty much the same as

echo test > file & tr -d t < file | wc > file; wait; cat file

which isn't much better in general in that it still contains all the same races, but at least it doesn't have the confusing pipe operator.

Zsh with multios is different in that makes multiple output redirections print to all targets, and multiple input redirections read from all sources. Instead of just the last one like a standard shell.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .