'Duplicate stdin to stdout

I am looking for a bash one-liner that duplicates stdin to stdout without interleaving. The only solution I have found so far is to use tee, but that does produced interleaved output. What do I mean by this:

If e.g. a file f reads

a
b

I would like to execute

cat f | HERE_BE_COMMAND

to obtain

a
b
a
b

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

a
a
b
b

Any suggestions for a clean solution?

Clarification

The cat f command is just an example of where the input can come from. In reality, it is a command that can (should) only be executed once. I also want to refrain from using temporary files, as the processed data is sort of sensitive and temporary files are always error-prone when the executed command gets interrupted. Furthermore, I am not interested in a solution that involves additional scripts (as stated above, it should be a one-liner) or preparatory commands that need to be executed prior to the actual duplication command.



Solution 1:[1]

Store the second input in a temp file.

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

Update: As shown in the comments (@j.a.) the solution above will need to be adjusted into the OP's real needs. Calling will be easier in a function and what do you want to do with errors in your initial commands and in the tee/cat/rm ?

Solution 2:[2]

I recommend tee /dev/stdout.

cat f | tee /dev/stdout

Solution 3:[3]

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 feel there must be a more "canonical" way of doing this using.

Solution 4:[4]

a simple bash script ? But this will store all the stdin, why not store the output to a file a read the file both if you need ?

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

Solution 5:[5]

The best way would be to store the output in a file and show it later on. Using tee has the advantage of showing the output as it comes:

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

If the amount of output is limited, you can do this:

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Yunnosch
Solution 3 Michael Schlottke-Lakemper
Solution 4
Solution 5