Duplicate stdin in stdout

I am looking for a single-line bash that duplicates stdin in stdout without interleaving. The only solution I have found so far is to use tee , but this has led to the issue of alternating output. What I mean:

If, for example, the file f reads

 a b 

I would like to perform

 cat f | HERE_BE_COMMAND 

To obtain

 a b a b 

If I use tee - as a command, the output usually looks something like

 a a b b 

Any suggestions for a clean solution?

Explanation

The cat f command is just an example of where the input might come from. This is actually a command that can (should) be executed only once. I also want to refrain from using temporary files, since the processed data is kind of sensitive, and temporary files are always prone to errors when an executable command is interrupted. In addition, I am not interested in a solution that includes additional scripts (as mentioned above, it should be single-line) or preparatory commands that must be executed before the actual duplication command.

+5
source share
5 answers

Solution 1:

 <command_which_produces_output> | { a="$(</dev/stdin)"; echo "$a"; echo "$a"; } 

This way you save the contents from standard input to a (choose the best name, please) and then echo 'twice.

Note $(</dev/stdin) is a similar but more efficient way to make $(cat /dev/stdin) .


Solution 2:

Use tee as follows:

 <command_which_produces_output> | tee >(echo "$(</dev/stdin)") 

Here you first write to the standard output (what tee does), and also writes to the FIFO file created by the process substitution :

 >(echo "$(</dev/stdin)") 

See, for example, the file that it creates on my system:

 $ echo >(echo "$(</dev/stdin)") /dev/fd/63 

Now the echo "$(</dev/stdin)" is what I found, first of all, to read the entire file before printing it. This echo is the content read from the standard process substitution input, but as soon as all the input is read (not like cat , which prints in turn).

+2
source

Save the second entry in a temporary file.

 cat f | tee /tmp/showlater cat /tmp/showlater rm /tmp/showlater 

Update: As shown in the comments (@ja), the above solution will need to be adjusted to the real needs of the OP. The call will be easier in function and what do you want to do with errors in your initial commands and in tee / cat / rm?

+2
source

One possible solution I found is the following awk command:

 awk '{d[NR] = $0} END {for (i=1;i<=NR;i++) print d[i]; for (i=1;i<=NR;i++) print d[i]}' 

However, I believe that there should be a more β€œcanonical” way of doing this with help.

0
source

simple bash script? But this will save all the stdin, why not save the output to a file by reading the file if you need to?

 full="" while read line do echo "$line" full="$full$line\n" done printf $full 
0
source

The best way is to save the output in a file and show it later. Using tee has the advantage of outputting the result:

 if tmpfile=$(mktemp); then commands | tee "$tmpfile" cat "$tmpfile" rm "$tmpfile" else echo "Error creating temporary file" >&2 exit 1 fi 

If the output is limited, you can do this:

 output=$(commands); echo "$output$output" 
0
source

Source: https://habr.com/ru/post/1234103/


All Articles