この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
朝起きたとき、ふとS3上の大量のファイルを移動したくなることありますよね。今朝の私がそうでした。
やりたいこと
以下のようにバケット上にhello_
とworld_*
から始まるファイルが複数あるとき、hello
で始まるファイルだけをhello
フォルダ以下に移動したいとします。
> aws s3 ls s3://your-bucket/
hello_1.txt
hello_2.txt
hello_3.txt
hello_4.txt
hello_5.txt
world_1.txt
world_2.txt
world_3.txt
world_4.txt
world_5.txt
include,exclude filters
このような場合にはフィルタオプションが便利です。
awsclli s3サブコマンドでは操作対象のキーを—include
および—exclude
の2つのオプションによってフィルタすることができます。
これらのオプションは複数回指定することができて、後に指定した条件が先に指定した条件に優先されます。
参考: Use of Exclude and Include Filters
フィルター順序の確認
フィルタの挙動を確認するためにいくつかのパターンを試してみます。
—includeが先の場合
hello_*.txtにマッチする条件がexcludeにかき消されてしまっていずれのファイルにもマッチしません。
> aws s3 mv s3://your-bucket \
s3://your-bucket/hello/ \
--include "hello_*.txt" \
--exclude "*" \
--recursive \
--dryrun
—excludeが先の場合
includeで指定した条件が優先されるのでhello_*.txt
だけにマッチします。これが今回やりたかった操作です。
> aws s3 mv s3://your-bucket \
s3://your-bucket/hello/ \
--exclude "*" \
--include "hello_*.txt" \
--recursive \
--dryrun
(dryrun) move: s3://your-bucket/hello_1.txt to s3://your-bucket/hello/hello_1.txt
(dryrun) move: s3://your-bucket/hello_2.txt to s3://your-bucket/hello/hello_2.txt
(dryrun) move: s3://your-bucket/hello_3.txt to s3://your-bucket/hello/hello_3.txt
(dryrun) move: s3://your-bucket/hello_4.txt to s3://your-bucket/hello/hello_4.txt
(dryrun) move: s3://your-bucket/hello_5.txt to s3://your-bucket/hello/hello_5.txt
—excludeがない場合
—recursive
によって全てのファイルが対象になるのでincludeの有無にかかわらず全ファイルがマッチする。
> aws s3 mv s3://your-bucket \
s3://your-bucket/hello/ \
--include "hello_*.txt" \
--recursive \
--dryrun
(dryrun) move: s3://your-bucket/hello_1.txt to s3://your-bucket/hello/hello_1.txt
(dryrun) move: s3://your-bucket/hello_2.txt to s3://your-bucket/hello/hello_2.txt
(dryrun) move: s3://your-bucket/hello_3.txt to s3://your-bucket/hello/hello_3.txt
(dryrun) move: s3://your-bucket/hello_4.txt to s3://your-bucket/hello/hello_4.txt
(dryrun) move: s3://your-bucket/hello_5.txt to s3://your-bucket/hello/hello_5.txt
(dryrun) move: s3://your-bucket/world_1.txt to s3://your-bucket/hello/world_1.txt
(dryrun) move: s3://your-bucket/world_2.txt to s3://your-bucket/hello/world_2.txt
(dryrun) move: s3://your-bucket/world_3.txt to s3://your-bucket/hello/world_3.txt
(dryrun) move: s3://your-bucket/world_4.txt to s3://your-bucket/hello/world_4.txt
(dryrun) move: s3://your-bucket/world_5.txt to s3://your-bucket/hello/world_5.txt
> aws s3 mv s3://your-bucket \
s3://your-bucket/hello/ \
--recursive \
--dryrun
(dryrun) move: s3://your-bucket/hello_1.txt to s3://your-bucket/hello/hello_1.txt
(dryrun) move: s3://your-bucket/hello_2.txt to s3://your-bucket/hello/hello_2.txt
(dryrun) move: s3://your-bucket/hello_3.txt to s3://your-bucket/hello/hello_3.txt
(dryrun) move: s3://your-bucket/hello_4.txt to s3://your-bucket/hello/hello_4.txt
(dryrun) move: s3://your-bucket/hello_5.txt to s3://your-bucket/hello/hello_5.txt
(dryrun) move: s3://your-bucket/world_1.txt to s3://your-bucket/hello/world_1.txt
(dryrun) move: s3://your-bucket/world_2.txt to s3://your-bucket/hello/world_2.txt
(dryrun) move: s3://your-bucket/world_3.txt to s3://your-bucket/hello/world_3.txt
(dryrun) move: s3://your-bucket/world_4.txt to s3://your-bucket/hello/world_4.txt
(dryrun) move: s3://your-bucket/world_5.txt to s3://your-bucket/hello/world_5.txt
まとめ
filterオプションはs3の他のサブコマンドでも使用できて、ローカルのファイルにも適用できるようです。
いつもはファイル一覧をgrepやxargsにパイプして操作をしていたのですが、ファイル数が多い場合はこの方がずっと効率がいいし単純になると思います。