How to List Only Modified Files in Rsync Transfers: A Developer’s Guide


2 views

When using rsync for deployment between staging and production environments, the default output can be overwhelmingly verbose. Using the command:

rsync -rzai --progress --stats --ignore-times --checksum /tmp/app_export/ root@app.com:/var/www/html/app/

We get output showing every file comparison, not just the modified files being transferred. This makes it difficult to quickly verify which files will actually change during deployment.

While grep fcst works as a basic filter, we can do better with rsync's built-in capabilities. The -i (--itemize-changes) flag actually provides all the information we need - we just need to interpret its output format.

Each line in the output represents:

YXcstpoguax path/to/file

Where the first 11 characters are flags indicating what changed. The key flags we care about are:

  • f - file is being transferred
  • c - checksum differs (file changed)

Combine the itemized output with grep to show only changed files:

rsync -rzai --dry-run --ignore-times --checksum /tmp/app_export/ root@app.com:/var/www/html/app/ | grep '^[^.]*c'

This regex matches lines where 'c' appears in the flags (indicating checksum difference) while ignoring other changes like permissions.

For a PHP deployment scenario, you might want to:

  1. See only changed PHP files:
    rsync -rzai --dry-run --ignore-times --checksum /tmp/app_export/ root@app.com:/var/www/html/app/ \
    | grep -E '^[^.]*c.*\.php$'
    
  2. Get machine-readable output for logging:
    rsync -rzai --dry-run --ignore-times --checksum /tmp/app_export/ root@app.com:/var/www/html/app/ \
    | awk '/^[^.]*c/ {print $2}'
    
  • The --checksum flag is crucial - it forces content comparison
  • --ignore-times ensures we don't skip files with identical timestamps
  • For very large transfers, consider adding --progress to monitor status

--out-format /h2>

For more control over output formatting in newer rsync versions (3.1.0+):

rsync -rzai --dry-run --ignore-times --checksum \
--out-format='%i %n' /tmp/app_export/ root@app.com:/var/www/html/app/ \
| grep '^c'

This gives cleaner output showing just changed files with their paths.


When running rsync for deployment between environments, we often face information overload. The standard output shows all files being compared, not just those actually being transferred. Here's what a typical deployment command might look like:

rsync -rzai --progress --stats --ignore-times --checksum /tmp/app_export/ root@app.com:/var/www/html/app/

The -i (itemize changes) flag is what generates the detailed output, but it shows everything. Each line begins with a status indicator:

  • fcst - File is being transferred (changed content)
  • .f... - File exists and is unchanged
  • cd++++ - Directory being created

Here are three effective ways to filter only modified files:

Method 1: Grep filtering

rsync -rzai --dry-run /source/ user@dest:/target/ | grep '^[^.]'

Method 2: Using --out-format (rsync 3.1.0+)

rsync -razi --out-format='%i %n' --dry-run /source/ user@dest:/target/ | awk '/^[^.]/ {print $2}'

Method 3: JSON output with jq (advanced parsing)

rsync -rai --dry-run --info=json /source/ user@dest:/target/ | jq -r 'select(.transfer_size > 0) | .path'

For PHP deployment scenarios, you might want to capture the changed files list into a variable:

changed_files=$(rsync -rzai --dry-run /tmp/app_export/ root@app.com:/var/www/html/app/ | grep '^[^.]' | awk '{print $2}')
echo "Files to be updated:"
echo "$changed_files"

Always combine with --dry-run for pre-deployment checks:

if rsync -rzai --dry-run /tmp/app_export/ root@app.com:/var/www/html/app/ | grep -q '^[^.]'; then
    echo "Changes detected, proceeding with deployment..."
    rsync -rzai /tmp/app_export/ root@app.com:/var/www/html/app/
else
    echo "No changes detected, skipping deployment."
fi

Remember that --checksum adds significant overhead as it verifies file contents. For large deployments, consider these alternatives:

  • Use --size-only for faster (but less accurate) comparisons
  • Implement incremental deployment strategies
  • Combine with versioned deployments when possible