← Blog
Two overlapping green and cream ceramic tiles with matching coral insets on a pale lavender background.
Published on
2026-11-09

AWS S3 cp: copy files, control overwrites, and verify transfers

aws s3 cp copies a local file to Amazon S3, downloads an object, or copies an object between S3 locations. Start with one small file and explicit source and destination paths. That makes it easier to catch a wrong key, unexpected overwrite, or missing permission before running a larger transfer.

This guide uses AWS CLI v2 and Amazon S3 general purpose buckets. It walks through a controlled upload, download, and bucket-to-bucket copy, then a filtered directory upload. Other S3-compatible services can support different options and behavior.

Choose cp for an explicit copy

Use cp when you have chosen the file or set of files to transfer. For recurring directory updates that depend on comparisons between source and destination, use our AWS S3 sync guide. Neither command replaces a recovery plan.

The basic order is aws s3 cp SOURCE DESTINATION. For a single object, a destination ending in / keeps the source filename; a full destination key lets you choose a different name. AWS explains these path and filter rules. The examples below use full filenames to make the intended result explicit.

Prepare a small transfer

Check your installed version and its available options:

aws --version
aws s3 cp help

The current cp reference, checked on November 9, 2026, includes --no-overwrite. Confirm that your local help lists it before using these examples. If it does not, update the CLI; do not remove the guard without reviewing existing destination files.

Use a configured profile named transfer-check, or replace it with your own. Replace both demonstration bucket names and the Regions with your actual test resources. Create a small, non-sensitive sample.csv in your working directory and an empty local directory named download-check. Use a new S3 prefix for each test run so that an earlier file cannot be mistaken for a new result.

The caller needs authorization for the operations involved, including reading the source and writing the destination. Encryption can add key permissions. Confirm the intended account and resource scope before transferring real data. Requests, retrieval, storage, and data transfer can incur charges.

Upload one file and inspect its destination

First preview the local-to-S3 copy:

aws s3 cp ./sample.csv s3://amzn-s3-demo-reports/cp-check/sample.csv --profile transfer-check --region eu-west-1 --no-overwrite --dryrun

Check that the preview names cp-check/sample.csv in the intended bucket. A dry run does not perform the transfer, so it cannot prove that the subsequent write will succeed. Once the paths are correct, run the same command without --dryrun:

aws s3 cp ./sample.csv s3://amzn-s3-demo-reports/cp-check/sample.csv --profile transfer-check --region eu-west-1 --no-overwrite

AWS’s high-level S3 command guide covers this transfer form. Keep the original file until you have checked the stored object and a downloaded copy. If a destination already exists, investigate that result instead of assuming this run uploaded new content.

Download to a fresh local path

aws s3 cp s3://amzn-s3-demo-reports/cp-check/sample.csv ./download-check/sample.csv --profile transfer-check --region eu-west-1 --no-overwrite --checksum-mode ENABLED

The target is the file inside the empty directory you prepared. --no-overwrite skips an existing destination; choose another fresh path if you need a new verification download. With checksum mode enabled, the CLI checks the object’s checksum when one is available. AWS’s checksum FAQ describes download validation. A successful command without an available checksum is not evidence that such validation occurred.

For this small fixture, compare the downloaded bytes with the original as described below. Do not download over the original file you intend to use for the comparison.

Copy an object between S3 buckets

After verifying the first upload, this example copies it to a different test bucket:

aws s3 cp s3://amzn-s3-demo-reports/cp-check/sample.csv s3://amzn-s3-demo-archive/cp-check/sample.csv --source-region eu-west-1 --region eu-west-2 --profile transfer-check --copy-props default --no-overwrite

Here the source bucket is in eu-west-1 and the destination is in eu-west-2. --source-region identifies the source; --region identifies the destination. --copy-props default preserves the supported metadata properties and tags and can require extra API calls.

This creates a destination copy and leaves the source in place. It does not duplicate the bucket’s access controls or configuration. AWS’s object-copy guidance explains destination encryption and cross-Region transfer charges. Inspect the destination’s settings rather than assuming they match the source.

Preview a filtered directory upload

Prepare exports/ with only the files you intend to test. This example selects CSV files while excluding the private/ subtree:

aws s3 cp ./exports/ s3://amzn-s3-demo-reports/cp-check/exports/ --recursive --exclude "*" --include "*.csv" --exclude "private/*" --no-follow-symlinks --no-overwrite --profile transfer-check --region eu-west-1 --dryrun

Filter order matters: begin by excluding everything, include CSV files, then exclude the private subtree. A later matching rule takes precedence. An include pattern alone does not narrow the default selection. Keep the patterns quoted so your shell passes them to the CLI.

Review every proposed destination before removing --dryrun. For example, exports/monthly/report.csv should map to cp-check/exports/monthly/report.csv; exports/private/payroll.csv should be excluded. The source directory itself is not an extra destination level.

--no-follow-symlinks avoids uploading files reached through local symbolic links. Keep unrelated files outside the test directory as well. For large transfers, our multipart upload guide covers parts and cleanup. The high-level CLI handles multipart uploads automatically when needed, but a failed command is not a persistent resumable upload session.

Decide how overwrites should work

The examples skip existing destinations. That is different from verifying their content: an old object can have the right name and the wrong bytes. Decide whether each workflow should create a new key, keep an existing file, or deliberately replace it.

For applications with concurrent writers, use an API operation with the required conditional-write precondition. Do not treat a separate existence check followed by a write as an atomic guarantee.

S3 Versioning can retain earlier object versions when a new write uses the same key. It does not prevent the latest version from changing, and retained versions consume storage. Our version-recovery guide explains how to recover an earlier object.

Verify the result, not just the progress line

Read the command’s exit code immediately: echo $? in Bash or $LASTEXITCODE in PowerShell. AWS’s return-code reference distinguishes success, transfer failures, skipped files, and parsing errors. A zero code from a dry run is still only a preview result.

Inspect the first uploaded object:

aws s3api head-object --bucket amzn-s3-demo-reports --key cp-check/sample.csv --profile transfer-check --region eu-west-1

HeadObject returns metadata without the body. Compare ContentLength with the source file and inspect content type, encryption information, and version ID when present. For the bucket-to-bucket copy, change the bucket and Region to the destination values. Equal sizes alone do not establish equal content.

Compare the original and downloaded fixture with a local SHA-256 tool. On Linux with sha256sum installed:

sha256sum ./sample.csv ./download-check/sample.csv

In PowerShell:

Get-FileHash -Algorithm SHA256 ./sample.csv, ./download-check/sample.csv

The two hashes should match. These commands compare local files after the download. Do not compare their output directly with an S3 ETag: AWS documents cases where an ETag is not the object’s MD5 digest, including multipart uploads. Checksums also have different algorithms, encodings, and full-object or composite forms.

If a transfer fails, retain the exact command, operation, error code, and request ID, with secrets removed. Check credentials and the source and destination permissions before changing policies. A useful first run ends with a known destination, checked metadata, and a verified small download. Expand to the full dataset only after those checks pass.

Your next workload belongs on Hivenet.

Pick one AI, compute, or storage workload and see the difference for yourself. Spin it up in minutes, or let our team map your fastest path to production.