Bash – How to use a variable instead of a file to output this wc command

bash

I want to read a file from a given offset until the end of that file.

I need to retrieve the number of bytes that were read during the process and also to redirect the output of the file elsewhere.

Here is my script:

...some stuff here...
dd if=$file bs=1 skip=$skippedBytes | tee >(wc --bytes > $file.count) >(cat - >> $file.output) | $($exportCommandString $file)
byteCount=$(cat $file.count)
rm $file.count
echo "Number of read bytes: $byteCount"

I would like the "wc –bytes" part to put its returned value inside a variable so I can use it after, without using a file ($file.count).

Something like:

dd if=$file bs=1 skip=$skippedBytes | tee >(byteCount=$(wc --bytes)) >(cat - >> $file.output) | $($exportCommandString $file)
echo "Number of read bytes: $byteCount"

Except that doing this, my script hangs and does not work.

Is it possible to do this and how ?

Best Answer

You can use a small hack with redirections:

byteCount=$( exec 3>&1 ; 
     dd if=$file  bs=1  skip=$skippedBytes | tee -a >(wc -c >&3) $file.output |\
     $($exportCommandString $file) > /dev/null ;  3>&1   )

It redirects all output to 3, that you've created with exec, and then returns it back to one at the end.

You also need to redirect all output from $exportCommandString to /dev/null, otherwise it will be mixed with wc output.

All stderr will work as usual, there is no any changes.

p.s.: you can use tee -a file instead of tee >(cat - >> file)).

p.p.s.: You can't export variables from subshell, which is always created while using pipe | in bash or $(). So there is no way to make something like

tee -a >(VAR=$(wc -c)) $file.output
Related Question