How to Make rsync Only Report Actually Transferred Files


2 views

When working with rsync for file synchronization between servers, many developers face this common challenge: either get bombarded with all file listings using -v (verbose) flag or receive no feedback at all when running silently. What we really want is selective output that only shows files that required actual transfer.

The solution lies in combining rsync's output filtering capabilities with the right flags. Here's the magic combination:

rsync -avzi --progress --out-format='%n' source/ destination/

Let's break down why this works:

  • -i (or --itemize-changes): Shows only files that were actually changed
  • --out-format='%n': Only displays the filename without extra metadata
  • --progress: Shows transfer progress for changed files

Here are some real-world scenarios where this approach shines:

# Example 1: Basic file transfer
rsync -azvi --out-format='[TRANSFER] %n' /local/webroot/ user@remote:/var/www/

# Example 2: Dry run with filtered output
rsync -navzi --out-format='[WOULD TRANSFER] %n' backup/ nas:/backups/

For more control over the output format, you can use these placeholders:

rsync -avzi --out-format='[%t] %i %n (Bytes: %l)' src/ dst/

This would produce output like:

[2023-12-15 10:00] >f..t...... index.html (Bytes: 4096)
[2023-12-15 10:00] >f.st...... config.php (Bytes: 1024)

For massive directories, you might want to log the transfers while keeping console output clean:

rsync -avzi --log-file=transfer.log --out-format='%n' big_data/ remote:backups/

When automating file transfers with rsync, many developers face this common scenario:

# Too verbose (shows all scanned files)
rsync -av /source/ user@remote:/destination/

# Completely silent (shows nothing)
rsync -a /source/ user@remote:/destination/

Rsync operates in two distinct phases when transferring files:

  1. Comparison phase (checks file differences)
  2. Transfer phase (actually moves data)

The -v flag affects both phases, making it impossible to distinguish between scanned files and actually transferred files in the output.

While rsync doesn't have a direct "show only transferred files" flag, we can achieve this with:

rsync -a --info=NAME1 --out-format='%n' /source/ user@remote:/destination/ | grep -v '/$'

This command:

  • Uses --info=NAME1 to show only names of files that are actually transferred
  • Formats output with --out-format to show just filenames
  • Filters out directories with grep -v '/$'

For a more detailed transfer report:

rsync -a --stats /source/ user@remote:/destination/ | \
  awk '/Number of regular files transferred:/ {p=1} p; /^$/ {p=0}'

This shows only the statistics section after the transfer completes.

Here's how I implement this in my deployment scripts:

#!/bin/bash
TRANSFER_LOG=$(mktemp)

echo "Starting deployment..."
rsync -a --info=NAME1 --out-format='%n' ./dist/ user@prod:/var/www/ > $TRANSFER_LOG

if [ -s $TRANSFER_LOG ]; then
  echo "Transferred files:"
  cat $TRANSFER_LOG | while read file; do
    echo "  - $file"
  done
else
  echo "No files needed transfer (already in sync)"
fi

rm $TRANSFER_LOG

In CI/CD pipelines or automated deployment systems, you want:

  • Clean logs showing only relevant changes
  • No noise from unchanged files
  • Clear indication of what was actually deployed

The techniques above provide exactly this while maintaining rsync's efficiency benefits.