microsoft-onedrive

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Drive Microsoft Graph for OneDrive / SharePoint via
curl + jq
. The user's OAuth bearer token is in
$MICROSOFT_ONEDRIVE_TOKEN
; every call needs it as
Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN
. The token already carries the OneDrive scopes the user agreed to at install time (
Files.Read
,
Files.Read.All
, optionally
Files.ReadWrite.All
,
Sites.Read.All
).
The Graph API returns standard JSON; failures surface as JSON
{"error": {"code": "...", "message": "..."}}
— show that error verbatim to the user.
Always start with
/me
to confirm the connection works AND learn which account / drive you're operating against.
通过
curl + jq
调用Microsoft Graph操作OneDrive/SharePoint。用户的OAuth bearer token存储在
$MICROSOFT_ONEDRIVE_TOKEN
中;每次调用都需要将其作为
Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN
传入。该令牌已包含用户在安装时同意的OneDrive权限范围(
Files.Read
Files.Read.All
,可选
Files.ReadWrite.All
Sites.Read.All
)。
Graph API返回标准JSON格式数据;调用失败时会返回JSON格式的错误信息
{"error": {"code": "...", "message": "..."}}
——请将该错误信息原封不动地展示给用户。
始终从
/me
接口开始
,以确认连接正常,并了解当前操作的账户/驱动器。

Recipes

操作指南

Verify auth (always run first)

验证权限(务必首先执行)

sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  https://graph.microsoft.com/v1.0/me \
  | jq '{displayName, mail, userPrincipalName}'
If you get
401 InvalidAuthenticationToken
, the token expired — report it; the user has to reinstall the connector.
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  https://graph.microsoft.com/v1.0/me \
  | jq '{displayName, mail, userPrincipalName}'
如果返回
401 InvalidAuthenticationToken
,说明令牌已过期——请告知用户,用户需要重新安装连接器。

List files in root

列出根目录下的文件

sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/me/drive/root/children?\$top=20&\$select=id,name,size,lastModifiedDateTime,folder,file" \
  | jq '.value[] | {id, name, size, kind: (if .folder then "folder" else .file.mimeType end), modified: .lastModifiedDateTime}'
Folders have
"folder":{"childCount":N}
, files have
"file":{"mimeType":"..."}
.
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/me/drive/root/children?\$top=20&\$select=id,name,size,lastModifiedDateTime,folder,file" \
  | jq '.value[] | {id, name, size, kind: (if .folder then "folder" else .file.mimeType end), modified: .lastModifiedDateTime}'
文件夹会包含
"folder":{"childCount":N}
字段,文件则包含
"file":{"mimeType":"..."}
字段。

List files in a sub-folder by path

通过路径列出子文件夹中的文件

sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/me/drive/root:/Documents:/children?\$top=20&\$select=id,name,size,lastModifiedDateTime"
Path uses
:
as the path/segment separator —
:/Documents/Q1:/children
.
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/me/drive/root:/Documents:/children?\$top=20&\$select=id,name,size,lastModifiedDateTime"
路径使用
:
作为路径段分隔符——例如
:/Documents/Q1:/children

Search files (recursive)

搜索文件(递归)

sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  --data-urlencode "q=quarterly report" --get \
  "https://graph.microsoft.com/v1.0/me/drive/root/search(q='quarterly report')?\$top=25&\$select=id,name,size,webUrl,lastModifiedDateTime"
search(q='')
with empty query returns 400. To find files by type without a keyword, search by extension:
search(q='.pdf')
.
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  --data-urlencode "q=quarterly report" --get \
  "https://graph.microsoft.com/v1.0/me/drive/root/search(q='quarterly report')?\$top=25&\$select=id,name,size,webUrl,lastModifiedDateTime"
如果
search(q='')
传入空查询会返回400错误。如果无需关键词,仅按类型查找文件,可以按扩展名搜索:
search(q='.pdf')

Recently modified files (cross-folder)

最近修改的文件(跨文件夹)

sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/me/drive/recent?\$top=25" \
  | jq '.value[] | {name, modified: .lastModifiedDateTime, parent: .parentReference.path}'
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/me/drive/recent?\$top=25" \
  | jq '.value[] | {name, modified: .lastModifiedDateTime, parent: .parentReference.path}'

Files shared with me

共享给我的文件

sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/me/drive/sharedWithMe?\$top=25" \
  | jq '.value[] | {name, size: .size, owner: .remoteItem.shared.owner.user.displayName}'
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/me/drive/sharedWithMe?\$top=25" \
  | jq '.value[] | {name, size: .size, owner: .remoteItem.shared.owner.user.displayName}'

Download a file by item id

通过项ID下载文件

sh
undefined
sh
undefined

/content returns 302 to a pre-signed URL — let curl follow it.

/content接口会返回302重定向到预签名URL——让curl自动跟随重定向。

curl -sSL -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}/content"
-o "$SKILL_DIR/tmp/$(basename "$NAME")"
undefined
curl -sSL -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}/content"
-o "$SKILL_DIR/tmp/$(basename "$NAME")"
undefined

Download a file by path

通过路径下载文件

sh
undefined
sh
undefined

URL-encode each path segment with jq -Rr @uri (or use printf encoding).

使用jq -Rr @uri对每个路径段进行URL编码(或使用printf编码)。

ENCODED=$(printf '%s' "Documents/report.docx" | jq -sRr @uri) curl -sSL -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
"https://graph.microsoft.com/v1.0/me/drive/root:/${ENCODED}:/content"
-o report.docx
undefined
ENCODED=$(printf '%s' "Documents/report.docx" | jq -sRr @uri) curl -sSL -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
"https://graph.microsoft.com/v1.0/me/drive/root:/${ENCODED}:/content"
-o report.docx
undefined

Upload a small file (< 4 MB)

上传小文件(< 4 MB)

sh
curl -sS -X PUT \
  -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @/tmp/report.pdf \
  "https://graph.microsoft.com/v1.0/me/drive/root:/Documents/report.pdf:/content"
For files > 4 MB use an upload session (chunked):
sh
undefined
sh
curl -sS -X PUT \
  -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @/tmp/report.pdf \
  "https://graph.microsoft.com/v1.0/me/drive/root:/Documents/report.pdf:/content"
对于文件**> 4 MB**使用上传会话(分块):
sh
undefined

1) create session

1) 创建会话

SESSION=$(curl -sS -X POST
-H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
-H "Content-Type: application/json"
-d '{"item":{"@microsoft.graph.conflictBehavior":"rename"}}'
"https://graph.microsoft.com/v1.0/me/drive/root:/Documents/big.zip:/createUploadSession") UPLOAD_URL=$(echo "$SESSION" | jq -r .uploadUrl)
SESSION=$(curl -sS -X POST
-H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
-H "Content-Type: application/json"
-d '{"item":{"@microsoft.graph.conflictBehavior":"rename"}}'
"https://graph.microsoft.com/v1.0/me/drive/root:/Documents/big.zip:/createUploadSession") UPLOAD_URL=$(echo "$SESSION" | jq -r .uploadUrl)

2) PUT in 10 MiB chunks with Content-Range: bytes <start>-<end>/<total>

2) 以10 MiB为分块执行PUT请求,设置Content-Range: bytes <start>-<end>/<total>

(See Microsoft Graph docs for the chunking loop; jq + dd makes this trivial.)

(分块循环的实现请参考Microsoft Graph文档;使用jq + dd可以轻松实现。)

undefined
undefined

Create a folder

创建文件夹

sh
curl -sS -X POST \
  -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Reports","folder":{},"@microsoft.graph.conflictBehavior":"rename"}' \
  https://graph.microsoft.com/v1.0/me/drive/root/children
@microsoft.graph.conflictBehavior
:
rename
(auto-suffix),
replace
(overwrite),
fail
(error if exists). Default is
fail
.
sh
curl -sS -X POST \
  -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Reports","folder":{},"@microsoft.graph.conflictBehavior":"rename"}' \
  https://graph.microsoft.com/v1.0/me/drive/root/children
@microsoft.graph.conflictBehavior
可选值:
rename
(自动添加后缀)、
replace
(覆盖)、
fail
(若已存在则返回错误)。默认值为
fail

Rename / move (PATCH)

重命名/移动文件(PATCH请求)

⚠️ Always show the source and destination before executing.
sh
undefined
⚠️ 执行前务必向用户展示源路径和目标路径。
sh
undefined

Rename only

仅重命名

curl -sS -X PATCH
-H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
-H "Content-Type: application/json"
-d '{"name":"renamed.docx"}'
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}"
curl -sS -X PATCH
-H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
-H "Content-Type: application/json"
-d '{"name":"renamed.docx"}'
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}"

Move to a different folder

移动到其他文件夹

curl -sS -X PATCH
-H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
-H "Content-Type: application/json"
-d "$(jq -nc --arg pid "$NEW_PARENT_ID" '{parentReference:{id:$pid}}')"
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}"
undefined
curl -sS -X PATCH
-H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
-H "Content-Type: application/json"
-d "$(jq -nc --arg pid "$NEW_PARENT_ID" '{parentReference:{id:$pid}}')"
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}"
undefined

Delete

删除文件

⚠️ Always fetch the item name first and confirm with the user.
sh
undefined
⚠️ 务必先获取文件名并征得用户确认后再执行。
sh
undefined

1) Show what will be deleted

1) 展示即将删除的内容

curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}?\$select=name,size,lastModifiedDateTime"
| jq '"Delete (.name) ((.size) bytes, modified (.lastModifiedDateTime))?"'
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}?\$select=name,size,lastModifiedDateTime"
| jq '"Delete (.name) ((.size) bytes, modified (.lastModifiedDateTime))?"'

2) After user confirms (returns 204 No Content)

2) 用户确认后执行(返回204 No Content表示成功)

curl -sS -X DELETE -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}"
-w "HTTP %{http_code}\n"
undefined
curl -sS -X DELETE -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN"
"https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}"
-w "HTTP %{http_code}\n"
undefined

Create a sharing link

创建共享链接

⚠️ Confirm with the user before sharing — this exposes data externally.
sh
curl -sS -X POST \
  -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"view","scope":"organization"}' \
  "https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}/createLink" \
  | jq '.link.webUrl'
type
:
view
|
edit
|
embed
.
scope
:
anonymous
|
organization
|
users
.
⚠️ 共享前务必征得用户确认——这会将数据暴露给外部。
sh
curl -sS -X POST \
  -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"view","scope":"organization"}' \
  "https://graph.microsoft.com/v1.0/me/drive/items/${ITEM_ID}/createLink" \
  | jq '.link.webUrl'
type
可选值:
view
|
edit
|
embed
scope
可选值:
anonymous
|
organization
|
users

List SharePoint sites

列出SharePoint站点

Requires
Sites.Read.All
.
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/sites?search=*&\$top=10" \
  | jq '.value[] | {id, name: .displayName, webUrl}'
Files inside a site:
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/sites/${SITE_ID}/drive/root/children?\$top=20"
需要
Sites.Read.All
权限。
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/sites?search=*&\$top=10" \
  | jq '.value[] | {id, name: .displayName, webUrl}'
站点内的文件:
sh
curl -sS -H "Authorization: Bearer $MICROSOFT_ONEDRIVE_TOKEN" \
  "https://graph.microsoft.com/v1.0/sites/${SITE_ID}/drive/root/children?\$top=20"

OData quick reference

OData快速参考

ParamExample
$select
id,name,size,lastModifiedDateTime
$filter
name eq 'report.docx'
,
size gt 1000000
$orderby
lastModifiedDateTime desc
$top
10
browsing,
25
search
$expand
children
,
permissions
Use
--data-urlencode "$key=$value" --get
with curl to avoid shell-quoting
$
and spaces.
参数示例
$select
id,name,size,lastModifiedDateTime
$filter
name eq 'report.docx'
,
size gt 1000000
$orderby
lastModifiedDateTime desc
$top
浏览时用
10
,搜索时用
25
$expand
children
,
permissions
使用
--data-urlencode "$key=$value" --get
配合curl,可避免shell对
$
和空格的转义问题。

Rules

规则

  • Always pass
    $select
    — defaults return 30+ fields per item.
  • $top=10
    for browse,
    25
    for search. Don't paginate past 50 unless asked.
  • URL-encode IDs if using them in a path — IDs can contain
    +
    ,
    /
    ,
    =
    . Use
    jq -sRr @uri
    .
  • Empty
    search(q='')
    returns 400
    — search by extension if you don't have a keyword.
  • 始终传入
    $select
    参数
    ——默认返回的每个项包含30多个字段。
  • 浏览时设置
    $top=10
    ,搜索时设置
    25
    。除非用户要求,否则分页不要超过50条。
  • 如果在路径中使用ID,请进行URL编码——ID可能包含
    +
    /
    =
    字符。使用
    jq -sRr @uri
    进行编码。
  • 空查询
    search(q='')
    会返回400错误
    ——如果没有关键词,请按扩展名搜索。

CRITICAL: User consent for destructive actions

重要提示:破坏性操作需用户同意

Never delete, overwrite or share without explicit confirmation. Pattern: prepare → present → execute.
ActionWhat to show user
Delete"Delete '{name}' ({size} bytes, modified {date})?"
Overwrite (
@microsoft.graph.conflictBehavior=replace
)
"Overwrite '{name}'? Existing: {size}, modified {date}"
Share (
createLink
)
"Create {type} link for '{name}' with {scope} access?"
Move"Move '{name}' from {old folder} to {new folder}?"
BulkCount + sample: "Delete 12 files in /Reports/?"
切勿在未获得用户明确确认的情况下执行删除、覆盖或共享操作。遵循流程:准备→展示→执行
操作需要向用户展示的内容
删除"是否删除'{name}'(大小{size}字节,最后修改时间{date})?"
覆盖(
@microsoft.graph.conflictBehavior=replace
"是否覆盖'{name}'?现有文件:大小{size},最后修改时间{date}"
共享(
createLink
"是否为'{name}'创建{type}类型、{scope}权限的共享链接?"
移动"是否将'{name}'从{旧文件夹}移动到{新文件夹}?"
批量操作数量+示例:"是否删除/Reports/下的12个文件?"

Errors

错误处理

  • 401 InvalidAuthenticationToken
    → token expired; user must reinstall the connector.
  • 403 accessDenied
    → scope missing (e.g. trying to write with read-only token); ask user to reinstall and tick the write scope.
  • 429 TooManyRequests
    → respect the
    Retry-After
    header (in seconds).
  • 404 itemNotFound
    → wrong id or path; double-check casing.
  • 401 InvalidAuthenticationToken
    → 令牌过期;用户必须重新安装连接器。
  • 403 accessDenied
    → 缺少权限范围(例如使用只读令牌执行写入操作);请用户重新安装并勾选写入权限。
  • 429 TooManyRequests
    → 遵守
    Retry-After
    响应头(单位为秒),等待后重试。
  • 404 itemNotFound
    → ID或路径错误;请检查大小写是否正确。

Reference

参考文档