AWS Tools for PowerShellで、AWS S3の指定フォルダ直下のフォルダを取得したかった。例えばバケット内に次のような構成があるとして…
AWSLogs/
+-- o-xxx9xxx9xx/
+-- 000000000000/
| +-- ap-northeast-1/
| :
+-- 111111111111/
:
… AWSLogs/o-xxx9xxx9xx/
直下の 000000000000/
111111111111/
…
というリストを得たい。
結論としては、以下のようにすればいい。
$objects = Get-S3ObjectV2 -BucketName $bucketName -Prefix "AWSLogs/o-xxx9xxx9xx/" -Delimiter "/" -Select CommonPrefixes
$objects
には以下が格納されている。型は文字列。
AWSLogs/o-xxx9xxx9xx/000000000000/
AWSLogs/o-xxx9xxx9xx/111111111111/
:
直下のものの取得: -Delimiter "/"
オプション
-Prefix
でのプレフィックス指定だけだと、内部的には「フルパスがこれに前方一致する」ものをすべて返してしまうので、「指定ディレクトリ以下のファイルを再帰的にリストアップする」ような動作になる。期待動作と違ったり、該当するものが多いと時間がかかったり上限(1度に1,000件まで)に引っかかったりする。
直下のもの=プレフィックスから次の /
までの要素だけを取得するには、 -Delimiter "/"
を指定する。
$objects = Get-S3ObjectV2 -BucketName $bucketName -Prefix "AWSLogs/o-xxx9xxx9xx/" -Delimiter "/"
フォルダーの取得:-Select CommonPrefixes
オプション
Get-S3ObjectV2
をそのまま実行すると、オブジェクト(ファイル的なもの)だけが返される。ディレクトリに相当するものはCommonPrefixと呼ばれており、取得したい時には -Select CommonPrefixes
を付ける。
$objects = Get-S3ObjectV2 -BucketName $bucketName -Prefix "AWSLogs/o-xxx9xxx9xx/" -Delimiter "/" -Select CommonPrefixes
フォルダ相当のものが、文字列型で返される。
PS> $objects[0]
AWSLogs/o-xxx9xxx9xx/000000000000/
PS> $objects[0].GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
参考
以下を参考にした。
AWS CLIやSDKでのS3利用経験があれば、わりとすぐに「 -Delimiter "/"
使うだけだろ、悩むとこある?」と思う気がする。でも実際には上述の通り「オブジェクトだけが返さ、CommonPrefixは返されない」ということになる。ここの解決方法を、このGitHubイシューで知った。
まず「パイプライン処理と $AWSHistory - AWS Tools for PowerShell」によれば、AWS Tools for PowerShellは次の挙動をする。
- コレクションを返すコマンドレットは、コレクション内のオブジェクトが返される。
- 内部で実行したAWS APIの結果値が、上のコレクションの他にページング制御フィールドではない追加フィールドを含む場合は、
$AWSHistory
セッション変数に記録される。
つまり、APIの実行結果そのままではない。Get-S3ObjectV2
コマンドレットであれば、Synopsysに書かれているように内部では S3 ListObjectsV2
APIを実行している。その結果値は以下で解説されている通り Contents
に格納されたオブジェクトのコレクションとは別に、 CommonPrefixes
にCommonPrefixが格納されている。
で、Get-S3ObjectV2
コマンドレットはそのAPIの実行結果から Contents
だけを抜き出されて返し、CommonPrefixはたぶん(確認してないけど)$AWSHistory
変数に格納する。前記のGithub Issueでは…
「そういういものだから」(2021.10.16)
「いやもっとわかりやすく」(2021.10.18)
「-Select CommonPrefixes
でもイケるっぽいけど、せめてドキュメントのExampleに入れようよ」(2022.5.13)
「わかったよドキュメント改定するよ」(2023.04.08)
…みたいなやり取りしてて、これ読んで-Select CommonPrefixes
でイケるのがわかって助かったけど、最後のコメントから1年余り経過した2024年5月10日現在、ドキュメントは改定されてないですよね?