- AWS
aws s3 syncの使い方 cpとの違いとexclude・delete早見表
aws s3 sync とは、コピー元とコピー先を比べて「無いもの・変わったもの」だけを転送する AWS CLI のコマンドです。 aws s3 cp --recursive が毎回すべてを送るのに対し、sync は差分だけを送り、--delete を付けるとコピー元から無くなったファイルをコピー先からも消せます。
この記事では、sync と cp の違い、主要オプション、--exclude と --include の順序ルール、そして「変更したのに同期されない」ときの原因を、すべて同じファイル構成で動かした出力つきでまとめます。
確認環境:Ubuntu 24.04 / AWS CLI 1.46.1。AWS の API をローカルで再現するツール(moto 5.2.3)で実行しました。掲載するコマンドは実際の AWS でそのまま使える形にしてあります(出力中のユーザー名とパスは taro、/home/taro に置き換えています)。
aws s3 sync の早見表
| やりたいこと | コマンド |
|---|---|
| ローカル → S3 に差分だけ送る | aws s3 sync site s3://demo-sync-bucket/site |
| S3 → ローカルに差分だけ取得する | aws s3 sync s3://demo-sync-bucket/site site |
| バケット間で差分だけコピーする | aws s3 sync s3://demo-sync-bucket/conf s3://demo-copy-bucket/conf |
| 何が起きるかを先に見る | --dryrun を付ける |
| コピー元に無いファイルをコピー先から消す | --delete を付ける |
| 特定のファイルを対象から外す | --exclude "logs/*" |
| 特定の種類だけ送る | --exclude "*" --include "*.log"(この順番で書く) |
| 1ファイルだけ送る | aws s3 cp site/index.html s3://demo-sync-bucket/site/index.html(sync ではなく cp) |
| サイズだけで差分を判定する | --size-only |
| S3 → ローカルで時刻が違えば取得する | --exact-timestamps |
| ストレージクラスを指定する | --storage-class STANDARD_IA |
| 進捗表示を消してログを読みやすくする | --no-progress |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「aws s3 syncの使い方 cpとの違いとexclude・delete早見表」
sync と cp --recursive の違い(比較表)
| 比べる点 | aws s3 sync |
aws s3 cp --recursive |
|---|---|---|
| 差分の判定 | する(サイズと更新時刻を比べる) | しない(毎回すべて転送) |
| 2回目の実行 | 変更が無ければ何も転送しない | 同じファイルをもう一度すべて転送 |
--delete |
使える | 使えない(Unknown options: --delete) |
| 単一ファイルの指定 | できない(ディレクトリ・プレフィックス同士) | できる(--recursive なしで1ファイル) |
--exclude / --include |
使える | 使える |
--dryrun |
使える | 使える |
| 向いている場面 | 繰り返し実行する配置・バックアップ | 初回の一括コピー、必ず上書きしたいとき |
以降の例は、次の7ファイルを使います。
site/README.md
site/css/style.css
site/index.html
site/js/app.js
site/logs/app.log
site/logs/debug.log
site/tmp/cache.tmp
2回目の実行で差が出る
1回目の sync は7ファイルすべてを送ります(--no-progress は進捗行を省くオプションです)。
aws s3 sync site s3://demo-sync-bucket/site --no-progress
upload: site/css/style.css to s3://demo-sync-bucket/site/css/style.css
upload: site/js/app.js to s3://demo-sync-bucket/site/js/app.js
upload: site/tmp/cache.tmp to s3://demo-sync-bucket/site/tmp/cache.tmp
upload: site/logs/app.log to s3://demo-sync-bucket/site/logs/app.log
upload: site/index.html to s3://demo-sync-bucket/site/index.html
upload: site/logs/debug.log to s3://demo-sync-bucket/site/logs/debug.log
upload: site/README.md to s3://demo-sync-bucket/site/README.md
何も変えずにもう一度実行すると、sync は何も出力せずに終わります(終了コード 0)。
aws s3 sync site s3://demo-sync-bucket/site
(出力なし)
同じ状態で cp --recursive を実行すると、7ファイルすべてがもう一度アップロードされました。
aws s3 cp site s3://demo-sync-bucket/site --recursive --no-progress
upload: site/README.md to s3://demo-sync-bucket/site/README.md
upload: site/js/app.js to s3://demo-sync-bucket/site/js/app.js
upload: site/index.html to s3://demo-sync-bucket/site/index.html
upload: site/css/style.css to s3://demo-sync-bucket/site/css/style.css
upload: site/logs/debug.log to s3://demo-sync-bucket/site/logs/debug.log
upload: site/logs/app.log to s3://demo-sync-bucket/site/logs/app.log
upload: site/tmp/cache.tmp to s3://demo-sync-bucket/site/tmp/cache.tmp
単一ファイルは cp を使う
sync にファイルを1つ渡すと、ディレクトリとして扱われて次の警告になります(終了コード 2)。
aws s3 sync site/index.html s3://demo-sync-bucket/site/index.html
warning: Skipping file /home/taro/work/site/index.html/. File does not exist.
1ファイルだけ送るなら cp が素直です。
aws s3 cp site/index.html s3://demo-sync-bucket/site/index.html --no-progress
upload: site/index.html to s3://demo-sync-bucket/site/index.html
sync のまま1ファイルに絞りたい場合は、--exclude "*" --include "index.html" と書けば同じ結果になります。
aws s3 sync site s3://demo-sync-bucket/site --no-progress --exclude "*" --include "index.html"
upload: site/index.html to s3://demo-sync-bucket/site/index.html
--delete は sync だけが受け付ける
ローカルで site/js/app.js を消したあとの出力です。--delete なしの sync は S3 側のファイルに触れません。--delete を付けると削除対象になります。
aws s3 sync site s3://demo-sync-bucket/site --delete --dryrun
(dryrun) delete: s3://demo-sync-bucket/site/js/app.js
cp に --delete を付けると、オプションとして受け付けられません(終了コード 255)。
aws s3 cp site s3://demo-sync-bucket/site --recursive --delete --dryrun
Unknown options: --delete
sync が「転送する」と判断する条件
公式リファレンス(aws s3 sync)には、ローカルから S3 への同期で転送対象になる条件が3つ書かれています。
| 条件 | 転送されるか |
|---|---|
| コピー先に同じ名前のオブジェクトが無い | される |
| サイズが違う | される |
| サイズは同じで、ローカルの更新時刻が S3 より新しい | される |
| サイズは同じで、ローカルの更新時刻が S3 より前 | されない |
中身(ハッシュ値)は比べていません。 この点が「同期されない」の多くの原因になります。後半の表で再現します。
オプション早見表(実行出力つき)
| オプション | 働き | 確かめた出力・結果 |
|---|---|---|
--dryrun |
実際には転送せず、行う操作だけを表示 | 各行の先頭に (dryrun) が付く |
--delete |
コピー元に無いファイルをコピー先から削除 | delete: s3://demo-sync-bucket/site/js/app.js |
--exclude "パターン" |
一致するものを対象から外す | --exclude "logs/*" で logs 配下の2件が消える |
--include "パターン" |
exclude で外したものを対象に戻す | --exclude "*" --include "*.log" で .log の2件だけ |
--size-only |
サイズだけで判定(更新時刻を見ない) | 同サイズの変更は出力なし、サイズが変わると upload |
--exact-timestamps |
S3 → ローカルで、同サイズでも時刻が違えば取得 | 既定で出力なしだったものが download になる |
--storage-class |
アップロード時のストレージクラス | list-objects-v2 で STANDARD_IA を確認 |
--no-progress |
進捗行(Completed ...)を出さない | upload / download / delete の行だけ残る |
--quiet |
操作の表示をすべて省く | 転送があっても出力なし |
--only-show-errors |
エラーと警告だけ表示 | 正常時は出力なし |
--cache-control |
Cache-Control を付けて送る | head-object で max-age=60 を確認 |
--content-type |
Content-Type を明示する | head-object で text/html; charset=utf-8 を確認 |
--storage-class に指定できる値は、公式リファレンスでは STANDARD / REDUCED_REDUNDANCY / STANDARD_IA / ONEZONE_IA / INTELLIGENT_TIERING / GLACIER / DEEP_ARCHIVE / GLACIER_IR で、既定は STANDARD です。
--dryrun:最初に必ず付けて確かめる
aws s3 sync site s3://demo-sync-bucket/site --dryrun
(dryrun) upload: site/README.md to s3://demo-sync-bucket/site/README.md
(dryrun) upload: site/css/style.css to s3://demo-sync-bucket/site/css/style.css
(dryrun) upload: site/index.html to s3://demo-sync-bucket/site/index.html
(dryrun) upload: site/js/app.js to s3://demo-sync-bucket/site/js/app.js
(dryrun) upload: site/logs/app.log to s3://demo-sync-bucket/site/logs/app.log
(dryrun) upload: site/logs/debug.log to s3://demo-sync-bucket/site/logs/debug.log
(dryrun) upload: site/tmp/cache.tmp to s3://demo-sync-bucket/site/tmp/cache.tmp
--delete や --exclude を使うときは、まず --dryrun で対象を見てから外す、という手順にすると安心です。
--storage-class:指定したクラスで保存する
aws s3 sync site/logs s3://demo-sync-bucket/archive --no-progress --storage-class STANDARD_IA
aws s3api list-objects-v2 --bucket demo-sync-bucket --prefix archive/ \
--query 'Contents[].[Key,StorageClass]' --output text
upload: site/logs/app.log to s3://demo-sync-bucket/archive/app.log
upload: site/logs/debug.log to s3://demo-sync-bucket/archive/debug.log
archive/app.log STANDARD_IA
archive/debug.log STANDARD_IA
--cache-control と --content-type:メタデータを付けて送る
aws s3 sync site s3://demo-sync-bucket/web --no-progress \
--exclude "*" --include "*.html" \
--cache-control "max-age=60" --content-type "text/html; charset=utf-8"
aws s3api head-object --bucket demo-sync-bucket --key web/index.html \
--query '[ContentType,CacheControl]' --output text
upload: site/index.html to s3://demo-sync-bucket/web/index.html
text/html; charset=utf-8 max-age=60
これらのメタデータは転送されたファイルにだけ付きます。sync は変更の無いファイルを送らないので、すでに S3 にあるオブジェクトへ後から付けたい場合は cp で送り直します。
--exclude と --include の順序ルール(4通りの dryrun)
ルールは「後ろに書いたフィルターが優先される」です。 そして、何も指定しない状態では全ファイルが対象(include 済み)です。空のバケットに対して、同じ7ファイルで4通りの並びを試しました。
A:exclude "*" → include "*.log"
aws s3 sync site s3://demo-sync-bucket/site --dryrun --exclude "*" --include "*.log"
(dryrun) upload: site/logs/app.log to s3://demo-sync-bucket/site/logs/app.log
(dryrun) upload: site/logs/debug.log to s3://demo-sync-bucket/site/logs/debug.log
B:include "*.log" → exclude "*"
aws s3 sync site s3://demo-sync-bucket/site --dryrun --include "*.log" --exclude "*"
(出力なし)
後ろの --exclude "*" がすべてを外すため、対象が0件になります。
C:exclude "logs/*" → include "logs/app.log"
aws s3 sync site s3://demo-sync-bucket/site --dryrun --exclude "logs/*" --include "logs/app.log"
(dryrun) upload: site/README.md to s3://demo-sync-bucket/site/README.md
(dryrun) upload: site/css/style.css to s3://demo-sync-bucket/site/css/style.css
(dryrun) upload: site/index.html to s3://demo-sync-bucket/site/index.html
(dryrun) upload: site/js/app.js to s3://demo-sync-bucket/site/js/app.js
(dryrun) upload: site/logs/app.log to s3://demo-sync-bucket/site/logs/app.log
(dryrun) upload: site/tmp/cache.tmp to s3://demo-sync-bucket/site/tmp/cache.tmp
logs 配下を外したうえで、app.log だけを戻せています(debug.log は外れたまま)。
D:include "logs/app.log" → exclude "logs/*"
aws s3 sync site s3://demo-sync-bucket/site --dryrun --include "logs/app.log" --exclude "logs/*"
(dryrun) upload: site/README.md to s3://demo-sync-bucket/site/README.md
(dryrun) upload: site/css/style.css to s3://demo-sync-bucket/site/css/style.css
(dryrun) upload: site/index.html to s3://demo-sync-bucket/site/index.html
(dryrun) upload: site/js/app.js to s3://demo-sync-bucket/site/js/app.js
(dryrun) upload: site/tmp/cache.tmp to s3://demo-sync-bucket/site/tmp/cache.tmp
後ろの exclude が勝つので、app.log も外れました。
4通りのまとめ
| 並び | 対象になったファイル | 読み方 |
|---|---|---|
A:--exclude "*" --include "*.log" |
.log の2件だけ | 全部外してから .log を戻す |
B:--include "*.log" --exclude "*" |
0件 | 最後の exclude がすべてを外す |
C:--exclude "logs/*" --include "logs/app.log" |
logs/debug.log 以外の6件 | 外した中から1件だけ戻す |
D:--include "logs/app.log" --exclude "logs/*" |
logs 以外の5件 | 最後の exclude が app.log も外す |
「絞り込みたいときは exclude を先、include を後」と覚えておくと迷いません。なお --include "*.log" だけを書いた場合は、もともと全ファイルが対象なので7件すべてが出力されました。include は「それだけを送る」指定ではなく、「外したものを戻す」指定です。
パターンにはシェルのワイルドカードに近い記法が使えます。--exclude "*" --include "*.[ch]*" を試すと、拡張子が c か h で始まる css/style.css と index.html の2件が対象になりました。パターンは必ず引用符で囲みます(囲まないとシェルが先に展開します)。
同期されない原因と対処(再現つき)
| 症状 | 原因 | 再現した結果 | 対処 |
|---|---|---|---|
| 中身を変えたのにアップロードされない | サイズが同じで、ローカルの更新時刻が S3 より前 | dryrun が出力なし | touch で時刻を更新する、または cp で送る |
| S3 側を更新したのにダウンロードされない | S3 → ローカルは、同サイズだと「ローカルのほうが新しいとき」だけ取得 | dryrun が出力なし | --exact-timestamps を付ける |
--size-only で変更が送られない |
サイズだけを比べるため、同サイズの変更は対象外 | dryrun が出力なし | --size-only を外す |
--exclude が効かない |
パターンはコピー元ディレクトリからの相対パスで評価される | site/logs/* では7件すべて対象のまま |
logs/* と書く |
| ディレクトリ名だけの exclude が効かない | logs や logs/ はファイルのパスと一致しない |
7件すべて対象のまま | logs/* と書く |
| ファイルを1つ指定したら転送されない | sync はディレクトリ・プレフィックス同士が対象 | warning: Skipping file ... |
cp を使う |
| 似た名前のプレフィックスまで対象になるか気になる | sync はプレフィックスをディレクトリとして扱う | conf の指定で conf-old/ は対象外 |
末尾スラッシュの有無は結果に影響しない |
サイズが同じで更新時刻が前のファイルは送られない
mode=A を mode=B に書き換え(どちらも7バイト)、更新時刻を S3 のオブジェクトより前の日時にしました。バックアップから戻したファイルや、時刻を保ったまま展開したファイルで起こる状況です。
echo 'mode=B' > conf/app.conf
touch -d '2026-01-01 00:00:00' conf/app.conf
ls -l --time-style=long-iso conf
aws s3 ls s3://demo-sync-bucket/conf/
aws s3 sync conf s3://demo-sync-bucket/conf --dryrun
-rw-r--r-- 1 taro taro 7 2026-01-01 00:00 app.conf
-rw-r--r-- 1 taro taro 4 2026-10-05 15:01 ver.txt
2026-10-05 15:01:25 7 app.conf
2026-10-05 15:01:25 4 ver.txt
dryrun の行が1つも出ません。サイズが同じで、ローカルのほうが新しくないため、sync は「変更なし」と判断しています。
対処1:更新時刻を今にすると対象になります。
touch conf/app.conf
aws s3 sync conf s3://demo-sync-bucket/conf --dryrun
(dryrun) upload: conf/app.conf to s3://demo-sync-bucket/conf/app.conf
対処2:そのファイルだけ cp で送ります。cp は判定をせずに上書きします。
aws s3 cp conf/app.conf s3://demo-sync-bucket/conf/app.conf --no-progress
aws s3 cp s3://demo-sync-bucket/conf/app.conf -
upload: conf/app.conf to s3://demo-sync-bucket/conf/app.conf
mode=B
--size-only は同サイズの変更を送らない
mode=B を mode=C に変えた直後(同じ7バイト、更新時刻は新しい)の比較です。
aws s3 sync conf s3://demo-sync-bucket/conf --dryrun
aws s3 sync conf s3://demo-sync-bucket/conf --dryrun --size-only
(dryrun) upload: conf/app.conf to s3://demo-sync-bucket/conf/app.conf
出力は1行だけで、これは1つ目(既定)のものです。--size-only を付けた2つ目は何も出しませんでした。内容を mode=CC(8バイト)にすると、--size-only でも対象になります。
echo 'mode=CC' > conf/app.conf
aws s3 sync conf s3://demo-sync-bucket/conf --dryrun --size-only
(dryrun) upload: conf/app.conf to s3://demo-sync-bucket/conf/app.conf
--size-only は、更新時刻だけが変わりやすい環境(ビルドのたびに全ファイルの時刻が新しくなる場合など)で、余分な転送を減らすのに向いています。設定ファイルのように同じ長さのまま書き換わるものには付けないほうが確実です。
S3 からローカルへの同期は時刻の向きが逆になる
S3 → ローカルでは、公式リファレンスの --exact-timestamps の説明にあるとおり、同サイズのファイルは「ローカルのほうが新しいとき」にだけ取得されます。S3 側を同じサイズのまま更新した場合を再現します。
aws s3 sync s3://demo-sync-bucket/conf dl --no-progress # いったん取得
echo 'mode=EE' > conf/app.conf # 同じ8バイトで書き換え
aws s3 sync conf s3://demo-sync-bucket/conf --no-progress # S3 側を更新
aws s3 sync s3://demo-sync-bucket/conf dl --dryrun # 既定
aws s3 sync s3://demo-sync-bucket/conf dl --dryrun --exact-timestamps
download: s3://demo-sync-bucket/conf/app.conf to dl/app.conf
download: s3://demo-sync-bucket/conf/ver.txt to dl/ver.txt
upload: conf/app.conf to s3://demo-sync-bucket/conf/app.conf
(dryrun) download: s3://demo-sync-bucket/conf/app.conf to dl/app.conf
最後の (dryrun) download は --exact-timestamps を付けた実行の出力です。既定の実行は何も出しませんでした。このときの時刻は、ローカルが 15:01:41、S3 が 15:02:17 で、S3 のほうが新しい状態です。
| 方向 | 同サイズのとき転送される条件(既定) | 揃えたいとき |
|---|---|---|
| ローカル → S3 | ローカルの更新時刻が S3 より新しい | touch するか cp で送る |
| S3 → ローカル | ローカルの更新時刻が S3 より新しい | --exact-timestamps を付ける |
逆に、ダウンロード後にローカルで同サイズの編集をすると、次の sync でそのファイルは S3 の内容に戻されます((dryrun) download: ... が出ることを確認しました)。ローカルで編集したファイルを残したい場合は、S3 → ローカルの sync の前に dryrun で確認しておくと安心です。
パターンの基準はコピー元ディレクトリ
aws s3 sync site ... のとき、パターンは site の中から見た相対パス(logs/app.log など)と比べられます。
aws s3 sync site s3://demo-sync-bucket/site --dryrun --exclude "site/logs/*"
(dryrun) upload: site/README.md to s3://demo-sync-bucket/site/README.md
…(省略)…
(dryrun) upload: site/logs/app.log to s3://demo-sync-bucket/site/logs/app.log
(dryrun) upload: site/logs/debug.log to s3://demo-sync-bucket/site/logs/debug.log
(dryrun) upload: site/tmp/cache.tmp to s3://demo-sync-bucket/site/tmp/cache.tmp
site/ を付けると一致せず、7件すべてが対象のままです。--exclude "logs/*" に直すと logs 配下の2件が外れ、5件になりました。--exclude "logs" と --exclude "logs/" も同じく7件のままだったので、ディレクトリごと外すときは ディレクトリ名/* と書きます。
末尾スラッシュとプレフィックスの扱い
バケットに conf/、conf-old/、config.txt がある状態で確かめました。
aws s3 ls s3://demo-sync-bucket --recursive
aws s3 sync s3://demo-sync-bucket/conf d1 --dryrun
aws s3 sync s3://demo-sync-bucket/conf/ d2 --dryrun
2026-10-05 15:01:43 4 conf-old/ver.txt
2026-10-05 15:01:41 8 conf/app.conf
2026-10-05 15:01:25 4 conf/ver.txt
2026-10-05 15:01:44 4 config.txt
(dryrun) download: s3://demo-sync-bucket/conf/app.conf to d1/app.conf
(dryrun) download: s3://demo-sync-bucket/conf/ver.txt to d1/ver.txt
(dryrun) download: s3://demo-sync-bucket/conf/app.conf to d2/app.conf
(dryrun) download: s3://demo-sync-bucket/conf/ver.txt to d2/ver.txt
sync では末尾スラッシュの有無で結果は変わりません。 conf と書いても conf-old/ や config.txt は対象になりませんでした。ローカル側も同じで、sync conf/ s3://demo-sync-bucket/x1 と sync conf s3://demo-sync-bucket/x1/ はどちらも x1/app.conf、x1/ver.txt になります。
末尾スラッシュで結果が変わるのは、次の2つです。
| コマンド | スラッシュなし | スラッシュあり |
|---|---|---|
aws s3 ls s3://demo-sync-bucket/conf |
PRE conf-old/、PRE conf/、config.txt(前方一致の一覧) |
app.conf、ver.txt(中身の一覧) |
aws s3 cp conf/ver.txt s3://demo-sync-bucket/backup |
backup という名前のオブジェクトになる |
backup/ver.txt になる |
--delete と --exclude を併用したときに消えるもの・残るもの
公式リファレンスの --delete の説明には「フィルターで除外されたファイルは削除からも除外される」とあります。S3 側に次の7件、ローカルは js/app.js を消した状態で確かめました。
site/README.md
site/css/style.css
site/index.html
site/js/app.js ← ローカルで削除済み
site/logs/app.log
site/orphan.txt ← S3 にだけある
site/tmp/remote-only.tmp ← S3 にだけある
フィルターなしの --delete:
aws s3 sync site s3://demo-sync-bucket/site --delete --dryrun
(dryrun) delete: s3://demo-sync-bucket/site/js/app.js
(dryrun) upload: site/logs/debug.log to s3://demo-sync-bucket/site/logs/debug.log
(dryrun) delete: s3://demo-sync-bucket/site/orphan.txt
(dryrun) upload: site/tmp/cache.tmp to s3://demo-sync-bucket/site/tmp/cache.tmp
(dryrun) delete: s3://demo-sync-bucket/site/tmp/remote-only.tmp
logs/* と tmp/* を除外した --delete:
aws s3 sync site s3://demo-sync-bucket/site --delete --dryrun --exclude "logs/*" --exclude "tmp/*"
(dryrun) delete: s3://demo-sync-bucket/site/js/app.js
(dryrun) delete: s3://demo-sync-bucket/site/orphan.txt
| S3 側のオブジェクト | フィルターなし | --exclude "logs/*" --exclude "tmp/*" |
|---|---|---|
js/app.js(ローカルで削除) |
消える | 消える |
orphan.txt(S3 にだけある) |
消える | 消える |
tmp/remote-only.tmp(S3 にだけある) |
消える | 残る(除外パターンに一致) |
logs/app.log(両方にある) |
残る | 残る(転送も削除もされない) |
exclude は「転送しない」だけでなく「削除もしない」という意味になります。 S3 側にだけ置いているファイル(別の仕組みが書き込むログなど)を --delete から守りたいときは、そのパスを exclude に入れます。反対に、除外したパスの不要ファイルは sync では消えないので、aws s3 rm で個別に消します。
ダウンロード方向でも同じ考え方で、aws s3 sync s3://demo-sync-bucket/conf dl --delete --dryrun を実行すると、ローカルにだけある dl/local-memo.txt が (dryrun) delete: dl/local-memo.txt と表示されました。--delete で消えるのは常にコピー先側です。
そのほかのメッセージと対処
| メッセージ | 状況 | 対処 |
|---|---|---|
The user-provided path nodir does not exist. |
コピー元のローカルディレクトリが無い | パスとカレントディレクトリを確認する |
fatal error: An error occurred (NoSuchBucket) when calling the ListObjectsV2 operation: The specified bucket does not exist |
バケット名の誤り | aws s3 ls でバケット名を確認する |
warning: Skipping file ... File does not exist. |
sync にファイルを指定した | cp を使う |
Unknown options: --delete |
cp に --delete を付けた |
sync を使う |
バケット間の sync も同じ判定で動きます。1回目は copy: の行が出て、2回目は出力なしでした。
aws s3 sync s3://demo-sync-bucket/conf s3://demo-copy-bucket/conf --no-progress
copy: s3://demo-sync-bucket/conf/app.conf to s3://demo-copy-bucket/conf/app.conf
copy: s3://demo-sync-bucket/conf/ver.txt to s3://demo-copy-bucket/conf/ver.txt
よくある質問
Q. sync と cp --recursive はどちらを使えばよいですか? A. 繰り返し実行するなら sync、初回の一括コピーや「必ず全部上書きしたい」ときは cp --recursive が向いています。sync は差分だけを送るので、2回目以降の転送量が小さくなります。
Q. 変更したファイルが sync で送られません。
A. サイズが同じで、ローカルの更新時刻が S3 より前になっていないかを確認します。touch で時刻を更新するか、そのファイルを cp で送ると反映されます。--size-only を付けている場合は外します。
Q. --delete を付けても安全に試す方法はありますか?
A. --dryrun を一緒に付けると、(dryrun) delete: の行で消える対象だけを確認できます。問題なければ --dryrun を外して実行します。
Q. --include だけを書いたら全部送られました。
A. 既定では全ファイルが対象なので、include だけでは絞り込めません。--exclude "*" --include "*.log" のように、先に全部外してから戻します。
まとめ
- sync は差分だけ、cp --recursive は毎回すべてを転送する。
--deleteは sync だけが受け付ける - 差分の判定はサイズと更新時刻。中身は比べないので、同サイズで時刻が前のファイルは送られない
- S3 → ローカルで同サイズの更新を取り込みたいときは
--exact-timestamps --excludeと--includeは後ろに書いたものが優先。絞り込みは exclude を先、include を後- パターンはコピー元ディレクトリからの相対パス。ディレクトリごと外すなら
logs/* --deleteと--excludeを併用すると、除外したパスは削除もされずに残る- 最初は必ず
--dryrunで対象を確認する
参考・出典
- AWS CLI Command Reference「s3 sync」(AWS CLI v1): https://docs.aws.amazon.com/cli/v1/reference/s3/sync.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「aws s3 syncの使い方 cpとの違いとexclude・delete早見表」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。