Efficiently Remove Empty Source Directories After rsync Transfers with –remove-source-files


2 views

When using rsync with --remove-source-files for directory transfers, we often encounter leftover empty source directories. While the flag successfully removes transferred files, directories remain intact, creating clutter and requiring manual cleanup.

rsync -axvvES --remove-source-files source_directory /destination/

This command effectively:

  • Preserves all attributes (-a)
  • Recurses into directories (-x)
  • Provides verbose output (-vv)
  • Handles sparse files efficiently (-S)
  • Removes source files after successful transfer

After execution, you'll typically find empty directory structures remaining in the source location. These serve no purpose yet require additional steps to remove.

Here's a robust solution combining rsync with find:

rsync -axvvES --remove-source-files source_directory /destination/ && \
find source_directory -depth -type d -empty -delete

Breaking it down:

  1. The rsync command performs the transfer and file removal
  2. The find command locates and removes empty directories:
    • -depth: Processes directories depth-first (children before parents)
    • -type d: Only matches directories
    • -empty: Only matches empty directories
    • -delete: Removes matching directories

For frequent use, create a bash script (e.g., rsync_move.sh):

#!/bin/bash
if [ $# -ne 2 ]; then
    echo "Usage: $0 source destination"
    exit 1
fi

rsync -axES --remove-source-files "$1" "$2" && \
find "$1" -depth -type d -empty -delete

Always verify transfers before automatic deletion:

# Dry run first
rsync -axvvESn --remove-source-files source_dir /dest/

# Then execute
rsync -axvvES --remove-source-files source_dir /dest/ && \
find source_dir -depth -type d -empty -exec echo "Would remove {}" \;

# Finally, remove after confirmation
find source_dir -depth -type d -empty -delete

While rsync's --prune-empty-dirs affects the destination only, we can combine it with our solution:

rsync -axvvES --remove-source-files --prune-empty-dirs source/ dest/ && \
find source -depth -type d -empty -delete

When using rsync to move files between directories with --remove-source-files, you'll notice empty directories remain in the source location. This happens because rsync's design focuses on file operations rather than directory management.

rsync -axvvES --remove-source-files source_directory /destination/

The rsync developers intentionally omitted directory removal for safety reasons:

  • Directories might contain hidden files (.dotfiles) or temporary files
  • Permissions issues could prevent proper directory inspection
  • Other processes might be using the directories

1. Combine rsync with find

This one-liner moves files and cleans empty directories:

rsync -axvvES --remove-source-files source/ destination/ \
  && find source/ -type d -empty -delete

2. Using --prune-empty-dirs with Caveats

The --prune-empty-dirs flag only works for the destination, but we can leverage it creatively:

rsync -axES --remove-source-files --prune-empty-dirs \
  --include='*/' --exclude='*' source/ destination/

3. Safe Directory Removal Script

For production environments, consider this more robust approach:

#!/bin/bash
SOURCE_DIR="/path/to/source"
DEST_DIR="/path/to/dest"

# Move files
rsync -aAXv --remove-source-files "$SOURCE_DIR"/ "$DEST_DIR"/

# Remove empty directories (with safety checks)
find "$SOURCE_DIR" -depth -type d -empty \
  -not -path "$SOURCE_DIR" \
  -exec rmdir -v {} \;

For simpler cases, consider these alternatives:

  • mv --remove-destination source/* destination/
  • cp -a --remove-destination source/* destination/ && rm -rf source/*

Always test with --dry-run first:

rsync -anv --remove-source-files source/ destination/
find source/ -type d -empty -print # shows what would be deleted

Remember that directory removal is permanent - implement proper backups before running these commands in production environments.