I know that tee will read from STDIN and create a new file. But when it comes with ls, which process happens first?
For example:
➤ ls
12 123 1234
➤ ls | tee hello
12
123
1234
hello # ls catch hello
➤ ls | tee 000
12
123
1234
hello # ls didn't get 000
➤ ls | tee 0
000
12
123
1234
hello # ls didn't get 0
➤ ls | tee 00000
0
000
00000 # ls did get 00000
12
123
1234
hello
➤
but when it comes to dir:
➤ ls
12 123 1234
➤ dir | tee hello
12 123 1234 hello # get hello
➤ dir | tee 000
000 12 123 1234 hello
➤ dir | tee 0
0 000 12 123 1234 hello #get 0
➤ dir | tee 000000
0 000 12 123 1234 hello # didn't get 00000
➤ dir | tee 01
0 000 000000 01 12 123 1234 hello
➤ dir | tee 000000000000000000000000
0 000 000000 000000000000000000000000 01 12 123 1234 hello #get 00000000..000
➤
WHY? Which happens first? tee create a new file or ls/dir output?
This is actually the case of a process-race-condition on a directory-resource since the two processes are executed in parallel.
The idea of pipeline is that
outputfrom process A associated with executable exec_A is redirected to process B associated with executable exec_B :exec_A | exec_BHow this is done is largely implementation dependent but given pragmatic limitations the operating system would have to create a buffer to place the output of A and force B to read from that buffer. This happens before processes start.
So what happens is something like:
exec_A &> buf ; exec_B < buf &What the processes do internally with the data they receive or write depends on the implementation of the process. In this case tee is creating the file that is going to write at process start, which is absolutely logical as it needs to append incoming data.
Given that, it depends on if process A ( i.e.
ls/dir) completes its directory transversal before process B has opened the file. Which is actually dependant on who obtains the lock on the resource's parent.You can actually observe that
lswill almost always output a resource that is created as such:ls * | tee subdir/0because it obtains the lock on
subdirlate.