Bobobk

Practical Python, Linux and automation guides

Rsync in Practice: Preview File Changes Before Syncing over SSH

2026-09-18 Technology
Rsync in Practice: Preview File Changes Before Syncing over SSH
On this page

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.

Tags

1024 2fa ablang adsense agents.md ai ai-agent ai-agents ai-seo algorithm amp antibodies apparmor argparse automation background backup bash batch-processing binarycif bioinformatics biopython blockchain boltz bootstrapping boxes bubblewrap c-index cca cdn checkpoint cli cloudflare codex cofoldarena concurrency configparser configuration copy cprofile cpu monitoring cron csv cuda curl data-leakage data-processing data-quality data-validation datascience datavisualization datetime debugging decimal deployment desktop-app devtools difflib disk-space disown dns docker dovecot download economics electron encoding esm esm2 esm3 esmc esmfold2 etag evaluation fable faceswap fasta fastmcp faulthandler ffmpeg file-descriptors file-io file-management filecmp filenames files flashppi flask folium frontend game generator git github-actions google google-research gpt-6.1-sol grep gzip harness heapq hls html http hugo imports indexnow ipaddress jailbreak javascript jev json jsonl just k-means kaggle langfuse leecode linux list litellm llm llms.txt logging logs lollipop lsof m3u8 machine-learning macos manacher matplotlib mcp memory mirror mmcif model-evaluation monitoring mp3 mp4 mpnn multiomics multiprocessing mutation mysql nanobert nanobodies networking networkx nginx normalize numpy ollama omegatherm pandas password pathlib pdb pep-723 performance permissions phaser pillow pip postfix preprocessing print probability prompt-engineering protein-alignment protein-design protein-embeddings protein-interactions protein-language-models protein-stability protein-structure proxy pydantic pyecharts pyqt python python3 r raincloud reproducibility requests reservoir-sampling rfoptimization rg ripgrep rosettafold3 roundcube rrsi rsi rsync s-tui sampling scale scikit-learn scrapy screen seaborn security seo sequence-identity sha256 shell signals sitemap sklearn socket solana somaticsignatures sorting spl sql sqlite ssh standardize static-site subprocess symlink sysadmin system-one tarfile tcp tempfile tensorflow tkinter tls toml totp tracemalloc trade tron tronpy troubleshooting turtle typesafe-ai ubuntu unicode upsert urllib usdt utf-8 uv venv vhhbert vite wallet web-tools webp wordcloud wordpress workflow xml yaml zipfile zoneinfo 迅雷解析

友情链接