【AWS-CLI】s3 syncコマンドのexclude/includeオプションを使って上手くサブフォルダーの中身をアップロードする


※ 当ページには【広告/PR】を含む場合があります。
2020/10/03
2024/01/05




AWS S3のファイルの中身を
『AWS CLI』 で管理している方も多いと思います。
特に、更新のあったファイルだけを自動で更新してくれる
s3 sync コマンドはとても重宝しております。
ユーザー側できめ細かいファイル管理を利用する際に使う
「--excludeと--include」 のオプションをシェルスクリプトの中で使う時の個人的なポイントを忘備録として残しておきたいと思います。


合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

「aws s3 sync」コマンドでS3バケットへ出し入れするファイルを細かく制御する



この記事も執筆したての時点では
「aws-cli v1」 を想定したないようでしたが、現状では 「aws-cli v2」 を念頭に解説していきます。
なお、「aws s3 sync」コマンドに関しては、v1からv2への移行で用法の目立った違いはありません。
特に意識することなく、そのまま利用可能です。

参考|s3 sync - aws cli command reference

以降では、「aws sync」コマンドの使いこなしのキモとなる「--exclude/--include」オプションの使い方を詳しくみていきます。


シェルコマンドを文字列から実行するテクニック



本題に入る前に頭に入れておいたほうが良い予備知識からお話しておきましょう。
特に
「aws s3 sync」 コマンドに限ったことではありませんが、一度にたくさんの引数を要求されるコマンドをワンライナーで実行する場合、一旦コマンドを文字列として生成してから、その文字列を実行させると便利なときがあります。
文字列を実行可能なコマンドとして扱うテクニックは以下の記事に移しましたので、不明な点はそちらでご確認ください。

合同会社タコスキングダム|蛸壺の技術ブログ
【シェルスクリプトツール作成の基本】文字列をシェルコマンドとして実行するアレコレ

evalコマンドを利用したコマンド引数の自動化のコツを理解する



結論だけいうと、
「文字列からコマンドを実行させるのはeval関数が鉄板」 という内容をこの別の記事で紹介していました。

「aws s3 sync」コマンドのテストにはドライランを使おう



通常、「aws sync」コマンドは、変更のあったファイルを根こそぎ書き換えてしまう破壊的な操作になります。
迂闊に叩いてしまったがために、S3バケットのデータを意図せず消してしまったり、ローカルの編集途中であったファイルが失われたりと、場合によっては取り返しのつかない自体になるかもしれません。
ローカルのフォルダとS3バケットを最初に同期させるときに、どのような結果になるのか、事前にシミュレートするコマンドオプションが、
「--dryrun」 です。
同期結果に少しでも不安を感じたら、本番実行前にこのオプションで実際に問題ないか確認することが可能です。

「aws s3 sync」コマンドの--exclude/--includeのフィルター制御



aws-cliのいくつかのコマンドのうち、操作の対象となるファイルをフィルタリングするための簡素な書式が用意されています。

参考|aws cliリファレンス

見てのように、正規表現などの強力なツールなどとは比べ物にならないくらいの貧弱な機能しかありません。--exclude/--includeのフィルター制御やフォルダを粒度細かくフィルター制御する場合には、
--exclude--include のオプションをチェーンにしてつないで使うより他はありません。

            $ aws sync --exclude "*" --include "*.png" --include "hoge/*.txt" --include "piyo/*.txt"

        

上記のコマンドが推奨される使い方の一例です。
一旦全てのファイルを
--exclude "*" で除外しておき、 --include でアップロードの対象にしたいファイルを追加していくようなやり方です。

--exclude オプションと --include オプションは何回も使えるものの、一度に複数の対象のファイル表現は出来ないので、このような数珠繋ぎな長い引数を取るようにしか使えないのが現状です。
場合によっては引数が長くなるので、一旦コマンドを文字列に落とし込んでから、その文字列をコマンドを実行するような場合に、上の節で説明したような
eval 関数以外でのやり方に注意が必要になってきます。
たとえば以下の例では、ルートフォルダにある
index.html と、引数で指定したルート直下にあるサブフォルダの中身を選択的に同期アップロードしたい場合のスクリプトとなります。

            #!/bin/bash

#👇アップロード対象となるローカルのフォルダ
DIST_FOLDER_PATH=/path/to/dist/folder

#👇アップロード先のS3バケットのアドレス
S3_BUCKET_PATH=s3://your-bucket.online/

subfolders=(${1//,/ })
for subfolder in "${subfolders[@]}"; do
    include_option="${include_option} --include '${subfolder}/*'"
done
include_option="aws s3 sync ${DIST_FOLDER_PATH} ${S3_BUCKET_PATH} --exclude '*' --include 'index.html' ${include_option}"

eval ${include_option}

        

サブフォルダの指定には、フォルダの名前をコンマ刻みの文字列で与え、引数で渡しています。
この引数を元に
aws sync が実行できる形式の文字列に変換し、 eval で実行するという流れです。
試しに、ルート直下にある
hoge / piyo / fuga というフォルダの中身を同期するようにしたい場合には、以下のように実行します。

            $ ./aws_sync.sh hoge,piyo,fuga
aws s3 sync /path/to/dist/folder s3://your-bucket.online/ --exclude '*' --include 'index.html' --include 'hoge/*' --include 'piyo/*' --include 'fuga/*'
#...同期アップロードが始まる

        

今回は簡単なスクリプトの例を示しました。
もっと複雑なアップロードが行いたければ、テキストファイルでホワイトリストを作成しておいて、
grep コマンドなどから読み取り、コマンド文字列を生成するなどの拡張が考えられます。
色々と応用の幅が広がりますが、今回はあまり深入りしないでおこうと思います。


合同会社タコスキングダム|蛸壺の技術ブログ【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書

まとめ



以上、「aws s3 sync」の細かいファイル選択のフィルター制御のネタを詳しく説明していきました。
個人的には鳴り物入りで出てきた「aws cli v2」だったので、「rsync」コマンド並みにパワーアップして利用できるのかと思ってましたが、表面上はv1時代のものをほぼ引き継いた形になっているようです。。。

合同会社タコスキングダム|蛸壺の技術ブログ
【シェルコマンド基礎講座】rsyncコマンドの使い方を細かく検証しながらinclude/excludeのコツを覚える

『rsync』コマンドを使う上で欠かせないinclude/excludeのフィルタパターンを理解する



ここらへんは、機能性よりも扱いやすさを重視されていると思い、良しとしましょう。