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) "%"} )
CodePudding user response:
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"} ')
CodePudding user response:
After a bit of struggle, I figured out how to use plutil
to convert the output of tmutil
into JSON. (The trick is that the first line is just raw text and must be discarded, but the rest is the property-list format that plutil
can parse.)
# Assuming the output shown in your question
% tmutil status | sed '1d' | plutil -convert -json -o - - | jq '.Progress| ._raw_Percent, .TimeRemaining'
0.1640944884974286
65013
This makes parsing more robust, and (with jq
) provides simpler input to a single awk
command, if you don't want to try your hand at producing the desired text in jq
itself.
Though zsh
can handle floating-point arithmetic itself, so you probably don't even need awk
. For example,
% tmutil status | ... | { read pct; read tr; }
% print "Percent complete: $(( tr * 100 ))%"
Percent complete: 16.409448849742862%