44

The Time Machine control panel gives information on in-progress backups. For example

enter image description here

Is there a way to get the information from the command line?

6 Answers 6

64

While the backup is running, detailed information gan be gained by

tmutil status

which should return something like this:

Backup session status:
{
    BackupPhase = Copying;
    ClientID = "com.apple.backupd";
    DateOfStateChange = "2014-12-18 14:14:21 +0000";
    DestinationID = "B4AF88-5AD5-49BE-B254-650B44E20499";
    DestinationMountPoint = "/Volumes/TimeMachine";
    Percent = "0.852581430477103";
    Progress =     {
        TimeRemaining = 0;
        "_raw_totalBytes" = 38596759;
        bytes = 36563200;
        files = 480;
        totalBytes = 42456434;
        totalFiles = 480;
    };
    Running = 1;
    Stopping = 0;
    "_raw_Percent" = "0.9473127005301144";
}

If you only care for the percentage, try the following (looks ugly, works only if there is a percentage to display):

tmutil status | awk '/_raw_Percent/ {print $3}' | grep -o '[0-9].[0-9]\+\(e-[0-9]\+\)\?' | awk '{print $1*100}'
7
  • 3
    I couldn't find this in the manpage. Where did you glean this verb for tmutil?
    – jsejcksn
    Dec 8, 2016 at 2:38
  • 5
    @jsejcksn To be honest, I don't remember where I found out about status, running tmutil help status now returns *** status is a private verb. ***; why this is the case and especially if this was the case two years ago, I don't know :D
    – Asmus
    Dec 9, 2016 at 9:42
  • 3
    What is the format of the data from tmutil? It's not quite JSON. Is it some kind of C object dump? Jan 27, 2018 at 16:44
  • 9
    @LS this is formatted as a NeXTSTEP-style property list
    – Asmus
    Feb 5, 2018 at 9:07
  • JSON files are somewhat brittle. Using a tool like jq which understands JSON to extract information might be a better approach. Oct 28, 2020 at 11:59
9

To get only the percentage value:

tmutil status | LC_NUMERIC="C" awk -F'"' '/_raw_Percent/ {print $4 * 100}'
1
  • Thank you! I used this with the watch command like this watch -n 2 "tmutil status | LC_NUMERIC='C' awk -F'\"' '/_raw_Percent/ {print \$4 * 100}'" to get an update e.g., every 2 seconds.
    – intagli
    Oct 23 at 23:58
1

I managed to make a simple script from the accepted answer.

tmstatus () {
  eval $(tmutil status | grep -E '[^}];$' | perl -p -e 's/^\s+[\"]*//g;' -e 's/[\"]*\s+\=\s+/=/g') || (echo "Something get wrong..." && return 1)

  if [[ $Running -eq 1 ]]
  then
    export LC_NUMERIC="en_US.UTF-8"
    [[ $BackupPhase == "Copying" ]] && Percent=$(printf '%0.2f%%' `bc <<< $Percent*100`) && echo "${DateOfStateChange} ${BackupPhase} backup to ${DestinationMountPoint}: ${totalFiles} files - ${Percent} (~$((${TimeRemaining:-0}/60)) min." || echo "${DateOfStateChange} ${BackupPhase} (Destination ${DestinationID})."
  else
    echo "TimeMachine backup is not running."
  fi
}
1

Maybe a bit more complicated but also more practical for processing, the following command will write the progress status into a plist file and convert it into json:

tmutil status | grep -v 'Backup session status' > a.plist; plutil -convert json a.plist

Json can be parsed more easily to extract various information.

0

I used @Atika's very helpful script but sometimes got errors like

bash: 26520.80484282512/60: syntax error: invalid arithmetic operator (error token is ".80484282512/60")

So I made a slight tweak to pass that division operation to bc and now it works reliably (caveat: for me!):

Before:

(~$((${TimeRemaining:-0}/60)) min."

After:

(~$(bc <<< ${TimeRemaining:-0}/60) min.)

Updated Script:

tmstatus () {
  eval $(tmutil status | grep -E '[^}];$' | perl -p -e 's/^\s+[\"]*//g;' -e 's/[\"]*\s+\=\s+/=/g') || (echo "Something get wrong..." && return 1)

if [[ $Running -eq 1 ]]
then
  export LC_NUMERIC="en_US.UTF-8"
  [[ $BackupPhase == "Copying" ]] && Percent=$(printf '%0.2f%%' $(bc <<< $Percent*100)) && echo "${DateOfStateChange} ${BackupPhase} backup to ${DestinationMountPoint}: ${totalFiles} files - ${Percent} (~$(bc <<< ${TimeRemaining:-0}/60) min.)" || echo "${DateOfStateChange} ${BackupPhase} (Destination ${DestinationID})."
else
  echo "TimeMachine backup is not running."
fi
}
0

I did a script for this that can be executed from Terminal.

https://github.com/fedekrum/Mac-Time-Machine-status

#!/bin/bash

# Check if we're root and re-run if not.
if [ $(id -u) -ne 0 ]; then
    echo "Script not running as root, trying to elevate to root..."
    sudo bash "$0" "$@"
    exit $?
fi
clear

# Get the PID of the process "/System/Library/CoreServices/backupd.bundle/Contents/Resources/backupd"
PID=$(ps -ef | awk '$8=="'/System/Library/CoreServices/backupd.bundle/Contents/Resources/backupd'" {print $2}')

# If the process is not found, it alerts the user and quits
if [ -z "$PID" ]; then
    echo "The process '/System/Library/CoreServices/backupd.bundle/Contents/Resources/backupd' is not running"
    exit 1
fi
clear

# Loop to continuously check the status
while true; do
    echo -e "\033[H"

    # Check if the output of "tmutil status" contains "ThinningPreBackup"
    if tmutil status | grep -q "ThinningPreBackup"; then
        # If it does, run "lsof -p $PID" and show the last line as the status
        echo
        printf "$(lsof -p $PID | tail -n 1 | awk -F'/[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{6}' '{print substr($2, 2)}')\n"
    else
        # If it doesn't, show the result of "tmutil status"
        echo
        printf "$(tmutil status)\n"
    fi

    # Get the width of the terminal
width=$(tput cols)

# Generate a line filled with spaces
line=$(printf '%*s' $width)

# Do it for three lines
for i in {1..3}; do
    # Print a carriage return and the line of spaces, effectively overwriting the current line with spaces
    echo -en "\r$line\r"

    # Move to the next line
    echo
done

    # Wait for 10 seconds before the next round
    for i in {10..1}; do
      echo -e "\033[H"
      echo "$i "
      sleep 1
    done
done
2
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Jul 31 at 9:46
  • Link only answers are not appreciated, especially if your GitHub account goes, then your answer is worthless. At least provide a copy of the script here (like other answers do), and explain it's workings. Jul 31 at 9:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .