google-drive

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Drive Google Drive via
curl + jq
. The user's OAuth bearer token is in
$GOOGLE_DRIVE_TOKEN
; every call needs it as
Authorization: Bearer $GOOGLE_DRIVE_TOKEN
. The token carries
drive.file
plus identity scopes (
openid email profile
) and can only access files the user selected, opened, created, or shared with this app.
The Drive API returns standard JSON; failures surface as
{"error": {"code": 401|403|..., "message": "..."}}
— show that error verbatim to the user.
401
means the token expired and the user must re-install the connector.
403 insufficientPermissions
means the file was not shared with this app, or the action needs a broader Drive scope that is temporarily disabled during Google review.
Do not use this skill for broad Drive discovery: no "list my recent files", full-text search across Drive, shared-with-me scans, root-folder cleanup, or bulk moves based on a Drive-wide query. Ask the user to pick or paste the exact file/folder IDs first.
Before any destructive write (renaming, moving, trashing, or bulk-mutating files) show the exact target list and ask the user to confirm. Never trash by guessing an id — always echo back the file name + path you're about to touch.
Always start with
/about?fields=user
to confirm the connection works AND learn which Google account you're operating against.
通过
curl + jq
操作Google Drive。用户的OAuth承载令牌存储在
$GOOGLE_DRIVE_TOKEN
中;每次调用都需要将其作为
Authorization: Bearer $GOOGLE_DRIVE_TOKEN
传入。该令牌包含
drive.file
权限以及身份范围(
openid email profile
),仅能访问用户选择、打开、创建或共享给本应用的文件。
Drive API返回标准JSON格式;失败时会返回
{"error": {"code": 401|403|..., "message": "..."}}
——请将该错误原封不动地展示给用户。
401
表示令牌已过期,用户必须重新安装连接器。
403 insufficientPermissions
表示文件未共享给本应用,或操作需要更广泛的Drive权限,而该权限在Google审核期间暂时被禁用。
请勿将此技能用于Drive的大范围检索:不支持“列出我的最近文件”、Drive全文搜索、扫描“与我共享”的文件、根文件夹清理,或基于Drive全局查询的批量移动操作。请先让用户选择或粘贴确切的文件/文件夹ID。
执行任何破坏性写入操作前(重命名、移动、删除或批量修改文件),请展示确切的目标列表并请求用户确认。切勿通过猜测ID来删除文件——务必回显您即将操作的文件名和路径。
**始终先调用
/about?fields=user
**以确认连接正常,并了解您正在操作的Google账户。

Optional: Google Workspace CLI (
gws
) for uploads

可选:用于上传的Google Workspace CLI(
gws

gws
is Google's official CLI (not officially supported — community-maintained on the
googleworkspace
org). It dynamically builds its command surface from Google's Discovery Document, exits non-zero on API errors, supports
--page-all
auto-pagination, and ships a
+upload
helper that wraps the multipart upload protocol.
Use
gws
for uploads.
A Drive multipart upload requires a hand-formatted
multipart/related
body with a JSON metadata part and a binary file part separated by a boundary string — easy to get wrong from curl.
gws drive +upload
does it correctly. For everything else (get, export, rename, move, trash, delete) the curl recipes below are equivalent and shorter — stay on those.
gws
是Google官方CLI工具(非官方支持——由
googleworkspace
组织的社区维护)。它会根据Google的Discovery Document动态构建命令界面,API错误时返回非零退出码,支持
--page-all
自动分页,并提供
+upload
助手来封装多部分上传协议。
上传操作请使用
gws
。Drive多部分上传需要手动格式化
multipart/related
请求体,包含JSON元数据部分和二进制文件部分,两者由边界字符串分隔——使用curl很容易出错。
gws drive +upload
能正确处理这一过程。其他所有操作(获取、导出、重命名、移动、删除、彻底删除)使用以下curl方案即可,它们功能等效且更简洁。

Install

安装

sh
npm install -g @googleworkspace/cli   # or: brew install googleworkspace-cli
sh
npm install -g @googleworkspace/cli   # 或:brew install googleworkspace-cli

预构建二进制文件也可在 https://github.com/googleworkspace/cli/releases 获取

gws --version
undefined
gws --version
undefined

Auth

认证

gws
reads its OAuth bearer token from the
GOOGLE_WORKSPACE_CLI_TOKEN
environment variable. The Drive token used in this skill is in
$GOOGLE_DRIVE_TOKEN
, so re-export it once at the top of every shell block that calls
gws
:
sh
export GOOGLE_WORKSPACE_CLI_TOKEN="$GOOGLE_DRIVE_TOKEN"
gws
GOOGLE_WORKSPACE_CLI_TOKEN
环境变量读取OAuth承载令牌。本技能中使用的Drive令牌存储在
$GOOGLE_DRIVE_TOKEN
中,因此在每个调用
gws
的shell块顶部,需重新导出一次:
sh
export GOOGLE_WORKSPACE_CLI_TOKEN="$GOOGLE_DRIVE_TOKEN"

Upload

上传

sh
undefined
sh
undefined

Simple upload to My Drive (auto-detects MIME type, sets the file name

简单上传到“我的云端硬盘”(自动检测MIME类型,通过--name设置文件名;若省略--name则使用本地文件名)

from --name; falls back to the local filename if --name is omitted)

gws drive +upload ./report.pdf --name "Q1 Report"
gws drive +upload ./report.pdf --name "Q1 Report"

Upload into a specific folder, or with explicit metadata, via the

上传到指定文件夹,或通过通用Discovery方法+--upload传入明确元数据(多部分传输格式已自动处理)

generic Discovery method + --upload (multipart wire format handled

for you)

gws drive files create
--json '{"name":"report.pdf","parents":["FOLDER_ID"],"description":"Q1"}'
--upload ./report.pdf

Both exit non-zero with a structured JSON error on stderr if Google
rejects the request — surface that verbatim.
gws drive files create
--json '{"name":"report.pdf","parents":["FOLDER_ID"],"description":"Q1"}'
--upload ./report.pdf

若Google拒绝请求,两者都会返回非零退出码,并在stderr输出结构化JSON错误——请将该错误原封不动地展示给用户。

Recipes

操作方案

Verify auth (always run first)

验证认证(务必先执行)

sh
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/about?fields=user(displayName,emailAddress,photoLink),storageQuota(usage,limit)" \
  | jq '{user, quota: .storageQuota}'
sh
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/about?fields=user(displayName,emailAddress,photoLink),storageQuota(usage,limit)" \
  | jq '{user, quota: .storageQuota}'

List children of a selected folder

列出指定文件夹的子项

Only use this after the user explicitly selected or provided the folder ID.
sh
FOLDER_ID='1A2B3CdEfGhIjKlMn'
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  --get "https://www.googleapis.com/drive/v3/files" \
  --data-urlencode "q='$FOLDER_ID' in parents and trashed = false" \
  --data-urlencode 'fields=files(id,name,mimeType,size,modifiedTime),nextPageToken' \
  | jq '.files'
仅在用户明确选择或提供文件夹ID后使用此操作。
sh
FOLDER_ID='1A2B3CdEfGhIjKlMn'
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  --get "https://www.googleapis.com/drive/v3/files" \
  --data-urlencode "q='$FOLDER_ID' in parents and trashed = false" \
  --data-urlencode 'fields=files(id,name,mimeType,size,modifiedTime),nextPageToken' \
  | jq '.files'

Get metadata for a single file

获取单个文件的元数据

sh
FILE_ID='1A2B3CdEfGhIjKlMn'
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=id,name,mimeType,size,modifiedTime,parents,owners,webViewLink,description"
sh
FILE_ID='1A2B3CdEfGhIjKlMn'
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=id,name,mimeType,size,modifiedTime,parents,owners,webViewLink,description"

Download a binary file (PDF / image / zip / …)

下载二进制文件(PDF/图片/压缩包/…)

sh
FILE_ID='1A2B3CdEfGhIjKlMn'
OUT=/tmp/download.bin
curl -sS -L -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID?alt=media" \
  -o "$OUT"
file "$OUT" && wc -c "$OUT"
sh
FILE_ID='1A2B3CdEfGhIjKlMn'
OUT=/tmp/download.bin
curl -sS -L -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID?alt=media" \
  -o "$OUT"
file "$OUT" && wc -c "$OUT"

Read a Google Doc as plain markdown / text

将Google Doc读取为纯markdown/文本

Google-native files (Docs, Sheets, Slides) don't have raw bytes — you have to ask Drive to export them to a concrete MIME type:
sh
DOC_ID='1A2B3CdEfGhIjKlMn'
Google原生文件(Docs、Sheets、Slides)没有原始字节数据——您需要请求Drive将其导出为具体的MIME类型:
sh
DOC_ID='1A2B3CdEfGhIjKlMn'

Markdown (best for chat-friendly summaries)

Markdown格式(最适合聊天场景的摘要)

curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN"
"https://www.googleapis.com/drive/v3/files/$DOC_ID/export?mimeType=text/markdown" \
/tmp/doc.md head -40 /tmp/doc.md
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN"
"https://www.googleapis.com/drive/v3/files/$DOC_ID/export?mimeType=text/markdown" \
/tmp/doc.md head -40 /tmp/doc.md

Plain text fallback for older docs

纯文本格式(兼容旧版文档)

curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN"
"https://www.googleapis.com/drive/v3/files/$DOC_ID/export?mimeType=text/plain" \
/tmp/doc.txt

Common export MIME types:

| native MIME | export to |
|---|---|
| `application/vnd.google-apps.document` | `text/markdown`, `text/plain`, `text/html`, `application/pdf`, `application/vnd.openxmlformats-officedocument.wordprocessingml.document` |
| `application/vnd.google-apps.spreadsheet` | `text/csv`, `application/pdf`, `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` |
| `application/vnd.google-apps.presentation` | `application/pdf`, `text/plain`, `application/vnd.openxmlformats-officedocument.presentationml.presentation` |
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN"
"https://www.googleapis.com/drive/v3/files/$DOC_ID/export?mimeType=text/plain" \
/tmp/doc.txt

常见导出MIME类型:

| 原生MIME类型 | 可导出为 |
|---|---|
| `application/vnd.google-apps.document` | `text/markdown`, `text/plain`, `text/html`, `application/pdf`, `application/vnd.openxmlformats-officedocument.wordprocessingml.document` |
| `application/vnd.google-apps.spreadsheet` | `text/csv`, `application/pdf`, `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` |
| `application/vnd.google-apps.presentation` | `application/pdf`, `text/plain`, `application/vnd.openxmlformats-officedocument.presentationml.presentation` |

Read a Google Sheet as CSV

将Google Sheet读取为CSV

sh
SHEET_ID='1A2B3CdEfGhIjKlMn'
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/files/$SHEET_ID/export?mimeType=text/csv" \
  > /tmp/sheet.csv
head /tmp/sheet.csv
The Drive
export
endpoint returns the first sheet only. For multi-tab access the user needs to install a separate Google Sheets connector (currently out of catalog) — explain that and stop.
sh
SHEET_ID='1A2B3CdEfGhIjKlMn'
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/files/$SHEET_ID/export?mimeType=text/csv" \
  > /tmp/sheet.csv
head /tmp/sheet.csv
Drive的
export
端点仅返回第一个工作表。若要访问多标签页,用户需要安装单独的Google Sheets连接器(目前不在目录中)——请向用户说明这一点并停止操作。

Get permissions / sharing on a file

获取文件的权限/共享设置

sh
FILE_ID='1A2B3CdEfGhIjKlMn'
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID/permissions?fields=permissions(id,type,role,emailAddress,domain,deleted)" \
  | jq '.permissions[] | {who: (.emailAddress // .domain // .type), role}'
sh
FILE_ID='1A2B3CdEfGhIjKlMn'
curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID/permissions?fields=permissions(id,type,role,emailAddress,domain,deleted)" \
  | jq '.permissions[] | {who: (.emailAddress // .domain // .type), role}'

Write recipes

写入操作方案

These only work for files and folders available through
drive.file
. If Google returns
403 insufficientPermissions
, surface the error and ask the user to select/share the target file with the app. Always echo the target name + path back to the user before trashing or bulk-moving anything.
这些操作仅适用于通过
drive.file
权限可访问的文件和文件夹。若Google返回
403 insufficientPermissions
,请展示错误信息并请求用户选择/共享目标文件给应用。在删除或批量移动任何内容前,务必回显目标文件名和路径给用户确认。

Rename a file

重命名文件

sh
FILE_ID='1A2B3CdEfGhIjKlMn'
NEW_NAME='2026 Q2 OKR (final).gdoc'
curl -sS -X PATCH -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H 'Content-Type: application/json' \
  --data "{\"name\":$(jq -nr --arg n "$NEW_NAME" '$n')}" \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=id,name"
sh
FILE_ID='1A2B3CdEfGhIjKlMn'
NEW_NAME='2026 Q2 OKR (final).gdoc'
curl -sS -X PATCH -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H 'Content-Type: application/json' \
  --data "{\"name\":$(jq -nr --arg n "$NEW_NAME" '$n')}" \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=id,name"

Move a file to a different folder

将文件移动到其他文件夹

Drive's folder model is parent-id based. Move = remove old parent, add new parent:
sh
FILE_ID='1A2B3CdEfGhIjKlMn'
NEW_PARENT='1XYZnewFolderId'
Drive的文件夹模型基于父ID。移动操作即移除旧父ID,添加新父ID:
sh
FILE_ID='1A2B3CdEfGhIjKlMn'
NEW_PARENT='1XYZnewFolderId'

Read existing parents (so we can pass them in removeParents)

读取现有父ID(以便在removeParents中传入)

OLD_PARENTS=$(curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN"
"https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=parents"
| jq -r '.parents | join(",")')
undefined
OLD_PARENTS=$(curl -sS -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN"
"https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=parents"
| jq -r '.parents | join(",")')
undefined

Create a new folder

创建新文件夹

sh
PARENT_ID='1XYZparentFolderId'  # or 'root' for My Drive root
curl -sS -X POST -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H 'Content-Type: application/json' \
  --data "{\"name\":\"Reports / 2026Q2\",\"mimeType\":\"application/vnd.google-apps.folder\",\"parents\":[\"$PARENT_ID\"]}" \
  "https://www.googleapis.com/drive/v3/files?fields=id,name,webViewLink" \
  | jq
sh
PARENT_ID='1XYZparentFolderId'  # 或使用'root'表示“我的云端硬盘”根目录
curl -sS -X POST -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H 'Content-Type: application/json' \
  --data "{\"name\":\"Reports / 2026Q2\",\"mimeType\":\"application/vnd.google-apps.folder\",\"parents\":[\"$PARENT_ID\"]}" \
  "https://www.googleapis.com/drive/v3/files?fields=id,name,webViewLink" \
  | jq

Upload a file (multipart so metadata + bytes go in one request)

上传文件(多部分请求,元数据和字节数据一次发送)

sh
LOCAL=/tmp/report.pdf
NAME='Q2 report.pdf'
PARENT_ID='1XYZparentFolderId'
MIME='application/pdf'

BOUNDARY='aceDataBoundary'
META=$(jq -nc --arg n "$NAME" --arg p "$PARENT_ID" '{name:$n, parents:[$p]}')
{
  printf -- '--%s\r\n' "$BOUNDARY"
  printf 'Content-Type: application/json; charset=UTF-8\r\n\r\n'
  printf '%s\r\n' "$META"
  printf -- '--%s\r\n' "$BOUNDARY"
  printf 'Content-Type: %s\r\n\r\n' "$MIME"
  cat "$LOCAL"
  printf '\r\n--%s--\r\n' "$BOUNDARY"
} > /tmp/_drive_upload.bin

curl -sS -X POST -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H "Content-Type: multipart/related; boundary=$BOUNDARY" \
  --data-binary @/tmp/_drive_upload.bin \
  "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,name,webViewLink" \
  | jq
For a media-only upload (no metadata) use
uploadType=media
; for files >5 MB use
uploadType=resumable
(covered in [Drive's docs] (https://developers.google.com/drive/api/guides/manage-uploads#resumable)).
sh
LOCAL=/tmp/report.pdf
NAME='Q2 report.pdf'
PARENT_ID='1XYZparentFolderId'
MIME='application/pdf'

BOUNDARY='aceDataBoundary'
META=$(jq -nc --arg n "$NAME" --arg p "$PARENT_ID" '{name:$n, parents:[$p]}')
{
  printf -- '--%s\r\n' "$BOUNDARY"
  printf 'Content-Type: application/json; charset=UTF-8\r\n\r\n'
  printf '%s\r\n' "$META"
  printf -- '--%s\r\n' "$BOUNDARY"
  printf 'Content-Type: %s\r\n\r\n' "$MIME"
  cat "$LOCAL"
  printf '\r\n--%s--\r\n' "$BOUNDARY"
} > /tmp/_drive_upload.bin

curl -sS -X POST -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H "Content-Type: multipart/related; boundary=$BOUNDARY" \
  --data-binary @/tmp/_drive_upload.bin \
  "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,name,webViewLink" \
  | jq
若要进行仅媒体上传(无元数据),请使用
uploadType=media
;若文件大于5 MB,请使用
uploadType=resumable
(详情见Drive文档)。

Replace the contents of an existing file

替换现有文件的内容

sh
FILE_ID='1A2B3CdEfGhIjKlMn'
LOCAL=/tmp/report-v2.pdf
curl -sS -X PATCH -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H 'Content-Type: application/pdf' \
  --data-binary @"$LOCAL" \
  "https://www.googleapis.com/upload/drive/v3/files/$FILE_ID?uploadType=media&fields=id,name,modifiedTime"
Metadata stays the same (id / parents / name) — only the bytes are replaced and Drive bumps
modifiedTime
.
sh
FILE_ID='1A2B3CdEfGhIjKlMn'
LOCAL=/tmp/report-v2.pdf
curl -sS -X PATCH -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H 'Content-Type: application/pdf' \
  --data-binary @"$LOCAL" \
  "https://www.googleapis.com/upload/drive/v3/files/$FILE_ID?uploadType=media&fields=id,name,modifiedTime"
元数据保持不变(ID/父文件夹/名称)——仅替换字节数据,Drive会更新
modifiedTime

Trash a file (or restore one)

删除文件(或恢复已删除文件)

sh
FILE_ID='1A2B3CdEfGhIjKlMn'
curl -sS -X PATCH -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"trashed":true}' \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=id,name,trashed"
sh
FILE_ID='1A2B3CdEfGhIjKlMn'
curl -sS -X PATCH -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"trashed":true}' \
  "https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=id,name,trashed"

Restore:

恢复:

curl -sS -X PATCH -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN"
-H 'Content-Type: application/json'
--data '{"trashed":false}'
"https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=id,name,trashed"

Prefer `trashed:true` over `DELETE` — `DELETE` is permanent and the
user can't undo it. Only use `DELETE` when they explicitly say
"permanently delete".
curl -sS -X PATCH -H "Authorization: Bearer $GOOGLE_DRIVE_TOKEN"
-H 'Content-Type: application/json'
--data '{"trashed":false}'
"https://www.googleapis.com/drive/v3/files/$FILE_ID?fields=id,name,trashed"

优先使用`trashed:true`而非`DELETE`——`DELETE`是永久删除,用户无法撤销。仅当用户明确要求“永久删除”时才使用`DELETE`。

Common error codes

常见错误码

HTTPmeaningwhat to tell the user
401 UNAUTHENTICATED
token expired / revoked"Reconnect the Google Drive connector on the Connections page."
403 insufficientPermissions
target not shared with app / broader Drive scope disabled"This file isn't available to the app under the current
drive.file
permission. Select or share the exact file with the Google Drive connector, then try again."
403 userRateLimitExceeded
quotaretry once after 5–10s; if it persists, tell the user.
404 notFound
wrong file id OR file isn't visible to this appdouble-check the id; ask the user to select or share the file with the connector.
400 invalidQuery
malformed
q
print the
q
you sent + the error message back to the user.
Never log or echo
$GOOGLE_DRIVE_TOKEN
— treat it as a secret.
HTTP状态码含义告知用户的内容
401 UNAUTHENTICATED
令牌过期/已撤销“请在连接页面重新连接Google Drive连接器。”
403 insufficientPermissions
目标文件未共享给应用/更广泛的Drive权限被禁用“当前
drive.file
权限下,该文件无法被应用访问。请选择或共享确切的文件给Google Drive连接器,然后重试。”
403 userRateLimitExceeded
配额超限等待5-10秒后重试一次;若仍失败,请告知用户。
404 notFound
文件ID错误或文件对应用不可见仔细检查ID;请用户选择或共享文件给连接器。
400 invalidQuery
查询格式错误将您发送的
q
参数和错误信息一并展示给用户。
切勿记录或回显
$GOOGLE_DRIVE_TOKEN
——请将其视为机密信息。