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:
- The rsync command performs the transfer and file removal
- 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.