[小ネタ]awscli でs3上の複数ファイルを移動する
はじめに
朝起きたとき、ふと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にパイプして操作をしていたのですが、ファイル数が多い場合はこの方がずっと効率がいいし単純になると思います。