How to Clean Up Temporary .partial Files After Failed Rsync Operations


2 views

When rsync gets interrupted (either manually with kill or due to system failures), it leaves behind temporary files with extensions like .zxivMN, .XXXXXX or .partial. These files can clutter your target directory and won't be automatically removed by subsequent rsync runs.

First, let's find all these temporary files. They typically follow these patterns:

find /target/directory -type f $-name ".*.??????" -o -name "*.partial"$ -ls

Example output would show files like:

./.document.pdf.zxivMN
./backup.sql.partial

Here are three approaches to clean up these files:

Method 1: Using find with xargs

find /target/directory -type f $-name ".*.??????" -o -name "*.partial"$ -print0 | xargs -0 rm -f

Method 2: Using find -exec

find /target/directory -type f $-name ".*.??????" -o -name "*.partial"$ -exec rm -f {} +

Method 3: Dry Run First

For safety, always do a dry run first:

find /target/directory -type f $-name ".*.??????" -o -name "*.partial"$ -exec echo "Would remove: " {} \;

The best solution is to prevent scattered temp files by specifying a dedicated partial directory:

rsync -ah --partial --partial-dir=.rsync-partials /source/ /target/

Then cleanup becomes simpler:

rm -rf /target/.rsync-partials

For more complex scenarios, consider this bash function:

clean_rsync_temp() {
    local target_dir=$1
    if [ ! -d "$target_dir" ]; then
        echo "Error: Directory doesn't exist" >&2
        return 1
    fi
    
    echo "Cleaning rsync temp files in $target_dir"
    find "$target_dir" -type f $-name ".*.??????" -o -name "*.partial"$ \
        -exec sh -c 'echo "Removing $0"; rm -f "$0"' {} \;
    
    # Also clean empty directories if needed
    find "$target_dir" -type d -empty -delete
}

When rsync is interrupted (especially with -a or --partial flags), it leaves behind temporary partial files with randomized extensions like .filename.randomchars. These files serve two purposes:

  1. Allow resuming interrupted transfers
  2. Ensure atomic file replacement (only when transfer completes successfully)

For immediate cleanup of these artifacts, you can use:

# Basic find command (safe version)
find /target/path -type f -name ".*.*" -size +0 -exec ls -l {} \;

# Aggressive cleanup (verify matches first!)
find /target/path -type f -name ".*.*" -exec rm -v {} \;

Add these rsync options to prevent accumulation:

rsync -ah --remove-source-files --partial-dir=/tmp/rsync-partial src/ dest/

Key parameters:

  • --partial-dir: Isolates temp files
  • --remove-source-files: Cleans up after verification
  • --delete-after: Post-transfer cleanup

For recurring sync jobs, create a maintenance script:

#!/bin/bash
TARGET="/mnt/archive1/documents"
DAYS_TO_KEEP=1

# Clean orphaned temp files older than N days
find "$TARGET" -type f -name ".*.*" -mtime +$DAYS_TO_KEEP -delete

# Verify cleanup
rsync -ah --dry-run --delete-excluded \
    --exclude='.*.*' \
    /mnt/archive1/ /mnt/archive2/

Special cases for different storage:

Filesystem Recommendation
NFS Use --inplace to reduce rename operations
ZFS Combine with zfs-auto-snapshot for rollback
Btrfs Leverage COW snapshots before major syncs