Search code examples
macoszshtee

How do I `tee` output to multiple piped commands with zsh on macOS?


I am using the tmutil status command to give me the current TimeMachine backup status. It gives an output of the sort

% tmutil status
Backup session status:
{
    BackupPhase = Copying;
    ClientID = "com.apple.backupd";
    DateOfStateChange = "2022-11-21 11:23:03 +0000";
    DestinationID = "89E08126-7132-4D14-80B4-EFD45E8C5BFC";
    FirstBackup = 1;
    Progress =     {
        Percent = "0.1640944884974286";
        TimeRemaining = 65013;
        "_raw_Percent" = "0.1640944884974286";
        "_raw_totalBytes" = 488603537408;
        bytes = 80177147549;
        files = 159679;
        totalBytes = 488603537408;
        totalFiles = 3345928;
    };
    Running = 1;
    Stopping = 0;
}

This is not JSON, though it looks a bit like it.

I want to report on the Percent Complete and the Time Remaining.

I can get the Percent Complete with

tmutil status | grep "raw_Percent" | LC_NUMERIC="C" awk -F '"' '{print "Percent Complete: " ($4 * 100) "%"} '

and I can get the Time Remaining with

tmutil status | grep "TimeRemaining" | awk '{print "Time Remaining: " ($3/3600) " hours"} '

How can I run tmutil once (it seems to be a little expensive), and send the output to two grep ... | awk ... commands?

My understanding is that I could do

tmutil status | tee > (grep "raw_Percent" | LC_NUMERIC="C" awk -F '"' '{print "Percent Complete: " ($4 * 100) "%"} ') | (grep "TimeRemaining" | awk '{print "Time Remaining: " ($3/3600) " hours"} ')

with each command (pipes and all) in brackets.

But, instead, I get

zsh: no matches found: (grep raw_Percent | LC_NUMERIC=C awk -F " {print "Percent Complete: " ($4 * 100) "%"} )

Solution

  • You are trying to redirect the standard output of tee to a subshell. What you want are two separate process substitutions, tee >(...) >(...). (Note the lack of a space between > and ( in each case.)

    As an aside, you don't need to use grep in either case; just let awk filter the lines.

    tmutil status | 
      tee >(LC_NUMERIC="C" awk -F '"' '/raw_Percent/ {print "Percent Complete: " ($4 * 100) "%"} ') \
          >(awk '/TimeRemaining/ {print "Time Remaining: " ($3/3600) " hours"} ')