はじめに
Cloud RunからGoogle Cloud Storage(GCS)のファイル一覧を取得したいときに、
「フォルダを指定したいのにできない!」とか、「01/aaa.zip が出てくるけど aaa.zip だけ欲しい!」というケース、結構ありますよね。
この記事では、Python+Cloud Run で
フォルダ配下のファイル一覧をシンプルに取得する方法をまとめます。
簡単なまとめ
| やりたいこと | 方法 |
|---|---|
| フォルダを指定して一覧を取る | prefix パラメータを使う |
| ファイル名だけ取りたい | os.path.basename() で変換 |
| 直下だけを取りたい | delimiter="/" を指定 |
| Cloud Run の権限設定 | 実行サービスアカウントに roles/storage.objectViewer を付与 |
実装例(Flask API)
flask
google-cloud-storage
from flask import Flask, request, jsonify
from google.cloud import storage
import os
app = Flask(__name__)
storage_client = storage.Client()
@app.route("/list")
def list_files():
bucket = request.args.get("bucket") # バケット名
prefix = request.args.get("prefix", "") # フォルダ名(例: 01/)
if not bucket:
return jsonify({"error": "bucket is required"}), 400
blobs = storage_client.list_blobs(bucket, prefix=prefix)
files = [os.path.basename(b.name) for b in blobs] # ← フォルダを除いたファイル名だけ抽出
return jsonify({
"bucket": bucket,
"prefix": prefix,
"files": files
})
デプロイ
Cloud Run にデプロイするだけで動きます。
gcloud run deploy gcs-listing \
--source . \
--region asia-northeast1 \
--allow-unauthenticated
呼び出し例:
curl "https://<your-service-url>/list?bucket=your-bucket&prefix=01/"
フォルダ構造の考え方
GCSは実際のフォルダ構造を持たず、ファイル名にスラッシュが含まれているだけです。
(これが誤解しがちな原因)
your-bucket/
├── 01/aaa.zip
├── 01/bbb.zip
└── 02/ccc.zip
内部的にはこんな感じのオブジェクト名になっています↓
01/aaa.zip
01/bbb.zip
02/ccc.zip
そのため、
bucket_name = "your-bucket/01" # ❌ 間違い
のようにフォルダ込みで指定するとエラーになります。
正しくは
bucket="your-bucket", prefix="01/"
のように分けて指定します。
フォルダを指定して取得する
blobs = client.list_blobs("your-bucket", prefix="01/")
これで "01/" の配下すべてを取得できます。
ファイル名だけ抽出する
import os
os.path.basename("01/aaa.zip") # => "aaa.zip"
複数ファイルなら:
files = [os.path.basename(b.name) for b in blobs]
「直下だけ」取りたいとき
サブフォルダを除外して、直下のファイルだけを取りたい場合は
delimiter="/" を指定します。
blobs = client.list_blobs("your-bucket", prefix="01/", delimiter="/")
files = [os.path.basename(b.name) for b in blobs]
subfolders = list(blobs.prefixes) # サブフォルダ名も取れる
Cloud Run 側の権限設定
Cloud Run の実行サービスアカウントに、
GCS への閲覧権限を付与します。
gcloud projects add-iam-policy-binding <YOUR_PROJECT_ID> \
--member="serviceAccount:<SERVICE_ACCOUNT>@<PROJECT_ID>.iam.gserviceaccount.com" \
--role="roles/storage.objectViewer"
よくあるエラー
| エラー | 原因 | 対処 |
|---|---|---|
| 403 Forbidden | 権限不足 | サービスアカウントに objectViewer 付与 |
| 404 Not Found | バケット名誤り | プロジェクトIDと混同しない |
| ファイルが出ない | prefix の末尾に / がない | "01" → "01/" に修正 |
| 01/aaa.zip で返る | GCSはフォルダ構造を持たない | os.path.basename() を適用 |
再帰的にすべて取る場合
サブフォルダも含めて全部取得したいときは
delimiter を付けずに prefix だけ指定します。
blobs = client.list_blobs("your-bucket", prefix="01/")
files = [b.name for b in blobs]
まとめ
| やりたいこと | コード例 |
|---|---|
| 全ファイル一覧 | list_blobs("bucket") |
| 特定フォルダ配下 | list_blobs("bucket", prefix="01/") |
| 直下だけ | list_blobs("bucket", prefix="01/", delimiter="/") |
| ファイル名だけ抽出 | os.path.basename(b.name) |
おわりに
Cloud Run と GCS を組み合わせると、
シンプルな「ファイル管理 API」や「自動処理トリガー」を簡単に作れます。
GCSの“フォルダ”はあくまで命名規則上の構造ですが、
prefix と delimiter を使い分ければ、
フォルダのように扱うことができます。