AWS S3 sync Command with Examples: Upload, Download, --delete and --exclude
aws s3 sync copies only the new or changed files between a local folder and an S3 bucket (or between two buckets). For example, aws s3 sync ./site s3://my-bucket uploads your website and skips files that are already the same. Add --dryrun to preview, --exclude to skip files, and --delete to remove files from the destination that no longer exist in the source. Use --delete only after a dry run, with S3 Versioning turned on.
Quick answer
aws s3 sync ./site s3://rb-site-2026 --dryrun # preview
aws s3 sync ./site s3://rb-site-2026 # upload changes
aws s3 sync s3://rb-site-2026 ./backup # download
aws s3 sync ./site s3://rb-site-2026 --delete --exclude ".git/*" # mirror
aws s3 sync s3://rb-logs-mumbai s3://rb-logs-dr --source-region ap-south-1 --region ap-southeast-1
A live example first
We host a static training site from the bucket rb-site-2026 (ap-south-1). The local build folder is ./dist.
- First upload, preview:
aws s3 sync ./dist s3://rb-site-2026 --dryrun
(dryrun) upload: dist/index.html to s3://rb-site-2026/index.html
(dryrun) upload: dist/css/site.css to s3://rb-site-2026/css/site.css
(dryrun) upload: dist/img/logo.png to s3://rb-site-2026/img/logo.png
- Run it for real (remove
--dryrun). Three files upload. - We edit only
index.htmland sync again:
aws s3 sync ./dist s3://rb-site-2026
upload: dist/index.html to s3://rb-site-2026/index.html
Only one file moved. That is the power of sync.
- We deleted
img/old-banner.pnglocally. The bucket still has it. To mirror exactly, preview with--delete:
aws s3 sync ./dist s3://rb-site-2026 --delete --dryrun
(dryrun) delete: s3://rb-site-2026/img/old-banner.png
It deletes only that one file, so we run it without --dryrun. Friends, never skip that preview when --delete is involved.
How does sync decide what to copy?
sync copies only new or changed files. Run --dryrun first, and turn on versioning before --delete.
For every file, sync checks whether it exists on the other side and compares size and last-modified time. If the file is missing or different, it copies it. If it matches, it skips it. It does not compare the content itself. Uploads larger than 8 MB are automatically split into multipart uploads.
How do I use sync step by step?
- Run
aws sts get-caller-identityto make sure you are in the right account. - Write the source first and the destination second.
- Add
--dryrunand read every line. - Add
--exclude/--includefilters if needed. - Run without
--dryrun. - For a static site behind CloudFront, invalidate the cache.
- Check with
aws s3 ls s3://bucket --recursive --human-readable --summarize.
Filters: --exclude and --include
Filters are applied in order, and later ones win:
# skip git and node_modules
aws s3 sync . s3://rb-site-2026 --exclude ".git/*" --exclude "node_modules/*"
# only upload HTML files
aws s3 sync . s3://rb-site-2026 --exclude "*" --include "*.html"
Useful options
| Option | What it does |
|---|---|
--dryrun |
Show actions, change nothing |
--delete |
Remove destination files not in source |
--exclude / --include |
Filter by pattern |
--size-only |
Compare size only (when timestamps are unreliable) |
--storage-class STANDARD_IA |
Cheaper class for backups |
--sse aws:kms |
Encrypt with KMS |
--cache-control "max-age=86400" |
Set browser caching headers |
--acl |
Avoid; modern buckets use bucket policies with ACLs disabled |
sync vs cp
aws s3 cp |
aws s3 sync |
|
|---|---|---|
| Copies | What you name (with --recursive for folders) |
Only new/changed files |
| Deletes extras | Never | With --delete |
| Best for | One file, a one-time copy | Repeated deploys, backups, mirrors |
Use it from your stack
- CI/CD (GitHub Actions, Jenkins, GitLab): run
aws s3 sync dist/ s3://bucket --deleteas the deploy step, using an IAM role, not stored keys. - Python (boto3): boto3 has no
sync; use the CLI from a script, or loop withupload_fileand compare ETags. - Node.js: call the CLI, or use the AWS SDK for JavaScript v3 with
@aws-sdk/lib-storagefor large uploads. - Backups from Linux: a nightly cron job such as
aws s3 sync /var/backups s3://rb-backups/$(hostname)/ --storage-class STANDARD_IA. - Other clouds:
gsutil rsync(Google Cloud) andazcopy sync(Azure) work the same way.
IAM permissions for sync
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::rb-site-2026" },
{ "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::rb-site-2026/*" }
]
}
Leave out s3:DeleteObject if the job should never delete.
Real example: why versioning matters
In 2014, the code-hosting company Code Spaces shut down after an attacker who got into its AWS console deleted most of its data, servers and backups, which all lived in the same account. A wrong --delete is a much smaller accident, but the protection is the same idea: turn on S3 Versioning (and for backups, a separate account and Object Lock), so a deleted or overwritten file can be restored.
Mistakes to avoid
- Swapping source and destination.
aws s3 sync s3://bucket ./site --deletedeletes your local work. - Using
--deletewithout--dryrun. - Syncing secrets.
.envfiles get uploaded too unless you exclude them.
Summary table
| Task | Command |
|---|---|
| Upload changes | aws s3 sync ./dir s3://bucket |
| Download | aws s3 sync s3://bucket ./dir |
| Preview | add --dryrun |
| Mirror | add --delete (after dry run) |
| Filter | --exclude / --include |
| Bucket to bucket | aws s3 sync s3://a s3://b |
Quick quiz: check what you learned
What does aws s3 sync copy?
- Only new or changed files
- Every file every time
- Only files under 5 GB
- Only files older than a day
Show answer
A. sync compares both sides and skips files that match.
Which flag shows what would happen without copying?
- --dryrun
- --quiet
- --recursive
- --no-progress
Show answer
A. --dryrun prints planned actions only.
Does sync delete extra files in the bucket by default?
- No, only with --delete
- Yes, always by default
- Only for .html files
- Only in us-east-1
Show answer
A. Deletion happens only when you add --delete.
What protects you if --delete removes the wrong files?
- S3 Versioning
- A bigger EC2 type
- A new IAM user
- An Elastic IP
Show answer
A. Versioning keeps older copies you can restore.
Learn it properly
These pages go deeper, with labs:
Frequently asked questions
What does aws s3 sync do?
It copies only new or changed files between a local folder and S3, or between two S3 locations. Files that are already the same are skipped.
What is the difference between s3 sync and s3 cp?
cp copies what you name (one file, or a folder with --recursive) every time. sync compares both sides and copies only differences, and can delete extras with --delete.
Does sync delete files by default?
No. Files only in the destination are kept unless you add --delete.
How does sync decide a file changed?
By default it compares size and last modified time. It does not compare file contents, so --exact-timestamps or a fresh copy may be needed in rare cases.
What permissions does sync need?
s3:ListBucket on the bucket and s3:GetObject / s3:PutObject on the objects. --delete also needs s3:DeleteObject.
How do I make a static site update show at once?
After sync, invalidate the CloudFront cache with aws cloudfront create-invalidation --paths "/*", or use versioned file names.