Rsync in Practice: Preview File Changes Before Syncing over SSH
You have changed two files in a folder and want to send the update to a server. Before running a copy command, it helps to answer two questions: where will the files land, and what will change there?
This exercise starts with disposable local folders. Once the results make sense, the same workflow can use the server name from the SSH configuration tutorial.
1. Prepare a small experiment
Check which implementation is installed:
rsync --version
The local exercise below was checked with macOS’s openrsync, reporting rsync 2.6.9 compatibility. Other implementations may format their output differently. If the command is missing, install rsync using your system’s package manager before continuing.
Run the following commands in one terminal, and keep that terminal open for the rest of the exercise:
demo_dir=$(mktemp -d)
mkdir -p "$demo_dir/source/notes" "$demo_dir/destination"
printf 'hello rsync\n' > "$demo_dir/source/hello.txt"
printf 'write a post\n' > "$demo_dir/source/notes/todo.txt"
printf 'demo metadata\n' > "$demo_dir/source/.DS_Store"
printf 'Working directory: %s\n' "$demo_dir"
The source now contains two text files and a dummy .DS_Store. Nothing in your existing project has changed.
2. Preview the transfer
rsync -rtin --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
Here, -r traverses directories, -t preserves modification times, -i lists individual changes, and -n requests a dry run. The exclusion skips the dummy metadata file. These basic options are documented in the openrsync manual.
The preview should mention hello.txt, notes/, and notes/todo.txt. Confirm that the destination is still empty:
ls -A "$demo_dir/destination"
No output is expected. Now remove only n from the option group:
rsync -rti --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
cat "$demo_dir/destination/hello.txt"
cat "$demo_dir/destination/notes/todo.txt"
The two messages should match the source. This example copies ordinary files and directories; it is not a complete backup recipe for permissions, ownership, symbolic links, or other filesystem metadata.
3. Check the source’s trailing slash
The first transfer produces this layout:
destination/
├── hello.txt
└── notes/
└── todo.txt
Compare it with a second, separate destination and a source without the final slash:
mkdir -p "$demo_dir/nested"
rsync -rti --exclude='.DS_Store' \
"$demo_dir/source" "$demo_dir/nested/"
cat "$demo_dir/nested/source/hello.txt"
This time, source becomes a directory inside nested. When preparing a real transfer, write down the intended final path of one file and check that the preview matches it.
4. Repeat the sync, then change one file
Run the original preview again:
rsync -rtin --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
For this unchanged sample, the itemized output should be empty. Append a line and try again:
printf 'second version\n' >> "$demo_dir/source/hello.txt"
rsync -rtin --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
Now hello.txt should appear. Run the corresponding command without n to copy the update.
By default, rsync selects file-content updates using size and modification time. An empty preview is therefore not a byte-for-byte integrity check. See the rsync manual’s description of its quick check.
5. Reuse your SSH host configuration
For the remote example, blogbox must already be a working Host entry in ~/.ssh/config. It can contain the account, address, and custom port, as described in the OpenSSH configuration reference.
Check the remote command and prepare a dedicated practice directory:
ssh blogbox 'rsync --version'
ssh blogbox 'mkdir -p "$HOME/rsync-demo"'
Rsync needs to be installed on both machines for this SSH transfer. The -e ssh option explicitly selects SSH as the transport. See the rsync setup documentation.
Preview the upload, then run it after reviewing the output:
rsync -rtin -e ssh --exclude='.DS_Store' \
"$demo_dir/source/" blogbox:rsync-demo/
rsync -rti -e ssh --exclude='.DS_Store' \
"$demo_dir/source/" blogbox:rsync-demo/
ssh blogbox 'cat "$HOME/rsync-demo/hello.txt"'
The relative remote path targets the login account’s home directory in a normal SSH setup. The result should contain both lines of hello.txt. Use this practice directory before substituting any production path. A dry run still connects to the server; it does not guarantee that the later write will succeed.
6. Observe what happens to destination-only files
Return to the local example:
printf 'keep me\n' > "$demo_dir/destination/destination-only.txt"
rsync -rti --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
cat "$demo_dir/destination/destination-only.txt"
The file remains. To see a deletion plan without applying it, run:
rsync -rtin --delete --exclude='.DS_Store' \
"$demo_dir/source/" "$demo_dir/destination/"
The preview should list destination-only.txt for deletion. Keep n in this exercise. Removing it would apply the deletion; the rsync manual explains the option’s scope.
Even without --delete, syncing can replace existing destination files with source versions. Keep recoverable copies when the destination contains work you cannot recreate.
When the real transfer fails
If rsync is missing remotely, install it on that machine. If SSH cannot resolve blogbox or authentication fails, return to the SSH troubleshooting steps. If the destination is unwritable, check the remote account and directory permissions.
For each new destination, repeat the same short sequence: preview, inspect paths, transfer, and check one resulting file. Once the command is stable, you can give it a reusable name with just.
- 原文作者:春江暮客
- 原文链接:https://www.bobobk.com/en/rsync-preview-sync-workflow.html
- 版权声明:本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
相关文章
- SSH Config in Practice: Use One Server Name in Terminals and Scripts
- Use just to Manage Project Commands: Turn Repeated Scripts into a Runnable Menu
- rg Tutorial: Why Many Developers Use ripgrep Instead of grep
- Codex Project Rules: Use AGENTS.md to Keep AI Coding Consistent
- Write Self-Contained Python Scripts with uv and PEP 723