破解飞书文档无法复制:完整复制技能 - 分块读取 + 分块写入,保持文字、表格、代码 100% 完整(图片除外)

# feishu-doc-copy - 飞书文档完整复制技能

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "破解飞书文档无法复制:完整复制技能 - 分块读取 + 分块写入,保持文字、表格、代码 100% 完整(图片除外)" with this command: npx skills add keson1521/feishu-doc-copy

feishu-doc-copy - 飞书文档完整复制技能

技能描述

功能:完整复制飞书云文档到同一账号的云空间,保持文字、表格、代码、格式 100% 一致(图片除外)。

适用场景

  • 有文档查看权限但无复制/下载权限
  • 需要备份飞书文档
  • 需要创建文档的完整副本
  • 长文档(>10,000 字符)的完整复制

前提条件

  • 对源文档有读取权限(能打开查看)
  • 有自己的云空间写入权限
  • 已安装 OpenClaw 并配置飞书渠道

限制

  • 图片无法复制(飞书 API token 权限限制)
  • 单次复制最大支持 100,000 字符

核心方法

分块读取 + 分块写入 + 严格验证

这是唯一可行的路径,因为:

  1. 飞书文档 API 单次读取有长度限制(limit 参数)
  2. 飞书文档编辑 API 单次写入有长度限制
  3. 文档无复制权限时,无法使用客户端复制粘贴
  4. 必须通过 API 分块搬运

完整实现流程

步骤 1:获取源文档信息

# 读取源文档前 50 字符,获取 total_length
openclaw feishu fetch-doc --doc_id <SOURCE_DOC_ID> --limit 50

返回值示例

{
  "doc_id": "ABC123xyz",
  "title": "文档标题",
  "total_length": 43548,
  "has_more": true,
  "length": 50,
  "markdown": "..."
}

关键信息

  • total_length:原文档总字符数(用于计算分块数量)
  • doc_id:源文档 ID

步骤 2:计算分块策略

# 每块大小:9000 字符(推荐值,避免切断表格/代码块)
BLOCK_SIZE=9000

# 计算分块数量
BLOCK_COUNT = ceil(TOTAL_LENGTH / BLOCK_SIZE)

示例

  • 原文档 43,548 字符
  • 每块 9,000 字符
  • 分块数量:ceil(43548/9000) = 5 块

分块偏移量

块 0: offset 0
块 1: offset 9000
块 2: offset 18000
块 3: offset 27000
块 4: offset 36000

步骤 3:创建临时目录

# 创建临时目录存储分块文件
TEMP_DIR="/tmp/feishu_copy_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$TEMP_DIR"

步骤 4:分块读取源文档

循环读取每一块

OFFSET=0
BLOCK_NUM=0

while [ $OFFSET -lt $TOTAL_LENGTH ]; do
  echo "读取块 $BLOCK_NUM(offset: $OFFSET)..."
  
  # 读取当前块
  openclaw feishu fetch-doc \
    --doc_id "$SOURCE_DOC_ID" \
    --limit $BLOCK_SIZE \
    --offset $OFFSET \
    > "$TEMP_DIR/chunk_${BLOCK_NUM}.json"
  
  # 提取 markdown 内容
  cat "$TEMP_DIR/chunk_${BLOCK_NUM}.json" | jq -r '.markdown' > "$TEMP_DIR/chunk_${BLOCK_NUM}.md"
  
  # 检查是否还有更多
  HAS_MORE=$(cat "$TEMP_DIR/chunk_${BLOCK_NUM}.json" | jq -r '.has_more')
  
  if [ "$HAS_MORE" = "false" ]; then
    echo "最后一块读取完成"
    break
  fi
  
  OFFSET=$(( $OFFSET + $BLOCK_SIZE ))
  BLOCK_NUM=$(( $BLOCK_NUM + 1 ))
  
  # 避免 API 限流
  sleep 0.5
done

关键验证点

  1. 每次读取后检查 has_more 标志
  2. 最后一块 has_more 必须为 false
  3. 每块文件必须成功保存

步骤 5:创建新文档

# 创建新文档(初始内容可以是任意占位符)
openclaw feishu create-doc \
  --title "<新文档标题>" \
  --markdown "# <新文档标题>\n\n正在搬运中..."

返回值示例

{
  "doc_id": "XYZ789abc",
  "doc_url": "https://www.feishu.cn/docx/XYZ789abc",
  "message": "文档创建成功"
}

记录新文档 IDNEW_DOC_ID


步骤 6:分块写入新文档

写入规则

  • 第 1 块(块 0):使用 overwrite 模式
  • 后续块(块 1-N):使用 append 模式
TOTAL_BLOCKS=$BLOCK_NUM  # 块编号从 0 开始,所以总块数 = 最大块编号 + 1

for i in $(seq 0 $BLOCK_NUM); do
  CHUNK_FILE="$TEMP_DIR/chunk_${i}.md"
  
  if [ $i -eq 0 ]; then
    MODE="overwrite"
    echo "写入块 $i($MODE 模式)..."
  else
    MODE="append"
    echo "追加块 $i($MODE 模式)..."
  fi
  
  # 写入当前块
  openclaw feishu update-doc \
    --doc_id "$NEW_DOC_ID" \
    --mode $MODE \
    --markdown @"$CHUNK_FILE"
  
  # 避免 API 限流
  sleep 1
done

关键验证点

  1. 第 1 块必须用 overwrite
  2. 后续块必须用 append
  3. 每次写入后检查返回状态
  4. 写入间隔至少 1 秒(避免限流)

步骤 7:验证结果

# 获取新文档信息
openclaw feishu fetch-doc \
  --doc_id "$NEW_DOC_ID" \
  --limit 50 \
  > "$TEMP_DIR/new_doc_info.json"

# 提取新文档总长度
NEW_LENGTH=$(cat "$TEMP_DIR/new_doc_info.json" | jq -r '.total_length')

# 计算差异
DIFF=$(( $TOTAL_LENGTH - $NEW_LENGTH ))
PERCENT=$(echo "scale=2; $NEW_LENGTH * 100 / $TOTAL_LENGTH" | bc)

echo "原文档:$TOTAL_LENGTH 字符"
echo "新文档:$NEW_LENGTH 字符"
echo "差异:$DIFF 字符($PERCENT% 完整)"

# 验证通过条件:差异 < 2%
if [ $(echo "$PERCENT < 98" | bc) -eq 1 ]; then
  echo "⚠️ 差异较大,请手动检查"
else
  echo "✅ 验证通过"
fi

预期结果

  • 差异 < 2%:正常(主要是图片 token 占位符差异)
  • 差异 > 5%:异常,需要检查哪块写入失败

步骤 8:清理临时文件

rm -rf "$TEMP_DIR"

完整自动化脚本

将以上流程整合为可执行脚本:

#!/bin/bash
# 飞书文档完整复制脚本
# 用法:./feishu-doc-copy.sh <源文档 ID> <新文档标题>

set -e  # 遇到错误立即退出

SOURCE_DOC_ID="$1"
NEW_DOC_TITLE="$2"
BLOCK_SIZE=9000  # 每块字符数

if [ -z "$SOURCE_DOC_ID" ] || [ -z "$NEW_DOC_TITLE" ]; then
  echo "用法:$0 <源文档 ID> <新文档标题>"
  echo "示例:$0 ABC123xyz 文档标题 - 副本"
  exit 1
fi

# 创建临时目录
TEMP_DIR="/tmp/feishu_copy_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$TEMP_DIR"

echo "📋 开始复制飞书文档..."
echo "   源文档 ID: $SOURCE_DOC_ID"
echo "   新文档标题:$NEW_DOC_TITLE"
echo "   临时目录:$TEMP_DIR"
echo ""

# 步骤 1: 获取源文档信息
echo "📊 步骤 1: 获取源文档信息..."
DOC_INFO=$(openclaw feishu fetch-doc --doc_id "$SOURCE_DOC_ID" --limit 50)
TOTAL_LENGTH=$(echo "$DOC_INFO" | jq -r '.total_length')
SOURCE_TITLE=$(echo "$DOC_INFO" | jq -r '.title')

echo "   源文档标题:$SOURCE_TITLE"
echo "   原文档总长度:$TOTAL_LENGTH 字符"

# 步骤 2: 计算分块数量
BLOCK_COUNT=$(( ($TOTAL_LENGTH + $BLOCK_SIZE - 1) / $BLOCK_SIZE ))
echo "   分块大小:$BLOCK_SIZE 字符/块"
echo "   分块数量:$BLOCK_COUNT 块"
echo ""

# 步骤 3: 分块读取
echo "📥 步骤 3: 分块读取源文档..."
OFFSET=0
BLOCK_NUM=0

while [ $OFFSET -lt $TOTAL_LENGTH ]; do
  echo "   读取块 $BLOCK_NUM(offset: $OFFSET)..."
  
  openclaw feishu fetch-doc \
    --doc_id "$SOURCE_DOC_ID" \
    --limit $BLOCK_SIZE \
    --offset $OFFSET \
    > "$TEMP_DIR/chunk_${BLOCK_NUM}.json"
  
  # 提取 markdown 内容
  cat "$TEMP_DIR/chunk_${BLOCK_NUM}.json" | jq -r '.markdown' > "$TEMP_DIR/chunk_${BLOCK_NUM}.md"
  
  # 检查是否还有更多
  HAS_MORE=$(cat "$TEMP_DIR/chunk_${BLOCK_NUM}.json" | jq -r '.has_more')
  
  if [ "$HAS_MORE" = "false" ]; then
    echo "   ✅ 最后一块读取完成"
    break
  fi
  
  OFFSET=$(( $OFFSET + $BLOCK_SIZE ))
  BLOCK_NUM=$(( $BLOCK_NUM + 1 ))
  
  sleep 0.5
done

TOTAL_BLOCKS=$BLOCK_NUM
echo "   ✅ 共读取 $(( $TOTAL_BLOCKS + 1 )) 块"
echo ""

# 步骤 4: 创建新文档
echo "📝 步骤 4: 创建新文档..."
NEW_DOC=$(openclaw feishu create-doc \
  --title "$NEW_DOC_TITLE" \
  --markdown "# $NEW_DOC_TITLE\n\n正在搬运中...")

NEW_DOC_ID=$(echo "$NEW_DOC" | jq -r '.doc_id')
NEW_DOC_URL=$(echo "$NEW_DOC" | jq -r '.doc_url')

echo "   新文档 ID: $NEW_DOC_ID"
echo "   新文档链接:$NEW_DOC_URL"
echo ""

# 步骤 5: 分块写入
echo "📤 步骤 5: 分块写入新文档..."

for i in $(seq 0 $TOTAL_BLOCKS); do
  CHUNK_FILE="$TEMP_DIR/chunk_${i}.md"
  
  if [ $i -eq 0 ]; then
    MODE="overwrite"
  else
    MODE="append"
  fi
  
  echo "   写入块 $i($MODE 模式)..."
  
  openclaw feishu update-doc \
    --doc_id "$NEW_DOC_ID" \
    --mode $MODE \
    --markdown @"$CHUNK_FILE"
  
  sleep 1
done

echo "   ✅ 所有块写入完成"
echo ""

# 步骤 6: 验证
echo "🔍 步骤 6: 验证结果..."

NEW_DOC_INFO=$(openclaw feishu fetch-doc --doc_id "$NEW_DOC_ID" --limit 50)
NEW_LENGTH=$(echo "$NEW_DOC_INFO" | jq -r '.total_length')

DIFF=$(( $TOTAL_LENGTH - $NEW_LENGTH ))
PERCENT=$(echo "scale=2; $NEW_LENGTH * 100 / $TOTAL_LENGTH" | bc)

echo "   原文档:$TOTAL_LENGTH 字符"
echo "   新文档:$NEW_LENGTH 字符"
echo "   差异:$DIFF 字符($PERCENT% 完整)"

if [ $(echo "$PERCENT >= 98" | bc) -eq 1 ]; then
  echo "   ✅ 验证通过(差异 < 2%,主要是图片 token)"
  VERIFICATION_STATUS="✅ 通过"
else
  echo "   ⚠️ 差异较大,请手动检查"
  VERIFICATION_STATUS="⚠️ 需检查"
fi
echo ""

# 步骤 7: 清理
echo "🧹 步骤 7: 清理临时文件..."
rm -rf "$TEMP_DIR"
echo "   ✅ 临时文件已清理"
echo ""

# 输出结果
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🎉 复制完成!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "   源文档:$SOURCE_TITLE"
echo "   新文档:$NEW_DOC_TITLE"
echo "   新文档链接:$NEW_DOC_URL"
echo "   完整性:$VERIFICATION_STATUS"
echo "   原文档:$TOTAL_LENGTH 字符"
echo "   新文档:$NEW_LENGTH 字符"
echo "   差异:$DIFF 字符"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

使用方法

方法 A:使用自动化脚本

# 1. 保存脚本
# 将上面的完整脚本保存为 ~/.openclaw/scripts/feishu-doc-copy.sh

# 2. 添加执行权限
chmod +x ~/.openclaw/scripts/feishu-doc-copy.sh

# 3. 执行
~/.openclaw/scripts/feishu-doc-copy.sh <源文档 ID> <新文档标题>

# 示例
~/.openclaw/scripts/feishu-doc-copy.sh ABC123xyz 文档标题 - 副本

方法 B:手动执行(适合调试)

# 1. 获取源文档信息
openclaw feishu fetch-doc --doc_id <SOURCE_DOC_ID> --limit 50

# 2. 创建临时目录
mkdir -p /tmp/feishu_copy_$$

# 3. 分块读取(假设原文档 43548 字符)
openclaw feishu fetch-doc --doc_id <SOURCE_DOC_ID> --limit 9000 --offset 0 > /tmp/feishu_copy_$$/chunk_0.json
openclaw feishu fetch-doc --doc_id <SOURCE_DOC_ID> --limit 9000 --offset 9000 > /tmp/feishu_copy_$$/chunk_1.json
openclaw feishu fetch-doc --doc_id <SOURCE_DOC_ID> --limit 9000 --offset 18000 > /tmp/feishu_copy_$$/chunk_2.json
openclaw feishu fetch-doc --doc_id <SOURCE_DOC_ID> --limit 9000 --offset 27000 > /tmp/feishu_copy_$$/chunk_3.json
openclaw feishu fetch-doc --doc_id <SOURCE_DOC_ID> --limit 9000 --offset 36000 > /tmp/feishu_copy_$$/chunk_4.json

# 4. 提取 markdown
for f in /tmp/feishu_copy_$$/chunk_*.json; do
  cat "$f" | jq -r '.markdown' > "${f%.json}.md"
done

# 5. 创建新文档
openclaw feishu create-doc --title "<新文档标题>" --markdown "# <新文档标题>\n\n正在搬运中..."

# 6. 分块写入
openclaw feishu update-doc --doc_id <NEW_DOC_ID> --mode overwrite --markdown @/tmp/feishu_copy_$$/chunk_0.md
openclaw feishu update-doc --doc_id <NEW_DOC_ID> --mode append --markdown @/tmp/feishu_copy_$$/chunk_1.md
openclaw feishu update-doc --doc_id <NEW_DOC_ID> --mode append --markdown @/tmp/feishu_copy_$$/chunk_2.md
openclaw feishu update-doc --doc_id <NEW_DOC_ID> --mode append --markdown @/tmp/feishu_copy_$$/chunk_3.md
openclaw feishu update-doc --doc_id <NEW_DOC_ID> --mode append --markdown @/tmp/feishu_copy_$$/chunk_4.md

# 7. 验证
openclaw feishu fetch-doc --doc_id <NEW_DOC_ID> --limit 50

验证清单

复制完成后,请检查以下项目:

必检项目

  • 字数验证:新文档字数 / 原文档字数 ≥ 98%
  • 目录完整:所有 ## 章节标题都存在
  • 表格完整:所有 <lark-table> 标签完整
  • 代码块完整:所有 ``` 代码块完整
  • 结语完整:文档结尾没有截断

选检项目

  • callout 格式正确
  • 列表格式正确
  • 粗体/斜体完整
  • 链接完整

常见问题

Q1: 为什么新文档字数比原文档少?

A: 正常现象,主要原因:

  1. 图片 token 占位符差异(每张约 100-150 字符)
  2. callout 内部换行被压缩(不影响渲染)
  3. 多余空白字符被清理

只要差异 < 2%,文档内容就是完整的。

Q2: 表格显示不正常怎么办?

A: 检查 <lark-table> 标签是否完整:

  • 必须有 rowscols 属性
  • 所有 <lark-tr><lark-td> 标签必须配对
  • 分块时没有在表格中间切断

Q3: 如何获取文档 ID?

A: 从飞书文档 URL 中提取:

URL: https://xxx.feishu.cn/wiki/DOC_ID_HERE
                                    ↑
                                文档 ID

文档 ID 是 URL 最后一段字符串。

Q4: 脚本执行失败怎么办?

A: 排查步骤:

  1. 检查是否有源文档读取权限(能打开查看)
  2. 检查 openclaw feishu 命令是否可用
  3. 检查临时目录是否有写入权限
  4. 查看错误输出,定位失败的步骤

Q5: 如何断点续传?

A: 如果写入中途失败:

  1. 不要删除临时目录
  2. 记录最后成功写入的块编号
  3. 从下一个块继续执行写入循环
  4. 完成后正常验证和清理

技术细节

分块大小选择

分块大小优点缺点推荐场景
5,000不易切断表格/代码API 调用次数多复杂文档
9,000平衡点-推荐
15,000API 调用次数少可能超过限制简单文档

API 限流处理

  • 读取间隔:0.5 秒
  • 写入间隔:1 秒
  • 如遇 429 错误:增加间隔时间

错误处理

脚本使用 set -e,遇到错误立即退出。临时文件保留,便于调试。


版本历史

  • v1.0 (2026-03-14): 初始版本
    • 分块读取 + 分块写入核心方法
    • 完整自动化脚本
    • 验证流程

许可证

MIT License


本技能基于 OpenClaw 飞书 API 实现,适用于所有有查看权限但无复制权限的飞书文档。

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

Leads

Leads - command-line tool for everyday use

Registry SourceRecently Updated
General

Bmi Calculator

BMI计算器。BMI计算、理想体重、健康计划、体重追踪、儿童BMI、结果解读。BMI calculator with ideal weight, health plan. BMI、体重、健康。

Registry SourceRecently Updated
General

Blood

Blood — a fast health & wellness tool. Log anything, find it later, export when needed.

Registry SourceRecently Updated
General

Better Genshin Impact

📦BetterGI · 更好的原神 - 自动拾取 | 自动剧情 | 全自动钓鱼(AI) | 全自动七圣召唤 | 自动伐木 | 自动刷本 | 自动采集/挖矿/锄地 | 一条龙 | 全连音游 - UI A better genshin impact, c#, auto-play-game, automatic, g...

Registry SourceRecently Updated