我正在转向 Linux,最后一个障碍是退出 OneNote。我想导出我的所有笔记本,这样每一页都会变成一个单独的 markdown 文件。
我尝试了很多方法——此主题提出了几条建议,但都过时了。
如果我可以让 OneNote 将所有页面导出为单独的 .docx 文件,那么使用 pandoc 将它们转换为单独的 markdown 文件就很容易了。但是,OneNote 只会将多个页面导出为单个文件。因此,一种方法是找到一种方法来自动单独导出每个页面。
另一种选择是一次将整个笔记本导出为 .docx 文件,用 pandoc 将它们转换为 markdown,然后拆分文件 - 但是,我对正则表达式的了解不够,无法让 csplit 仅使用其基本正则表达式正确地剪切文件,我对 awk 的了解也不够,无法让它使用正确和完整的正则表达式输出文件。
谁能帮我这个?
答案1
我最终找到了一条导出管道,但这很麻烦。以下是我这样做的笔记:
工作流程:
关闭您的网络以防止 OneNote 在每次导出后执行冗长的 OneDrive 同步。
在笔记本列表中,展开笔记本以查看所有选项卡。
右键单击一个选项卡,然后单击“导出...”。
单击文件类型下拉菜单并按下M选择
.docx
格式。按下Enter选择它。再次按下Enter即可保存导出的文件。
对笔记本中的每个选项卡重复步骤 2-5。
设置 pandoc 并打开 PowerShell 或 cmd 窗口。
cd 进入导出文件所在的目录
.docx
。对于每个导出的
.docx
文件,使用以下 pandoc 命令将其转换为 markdown(替换journal
为文件的名称):pandoc --extract-media='' --wrap=preserve '.\journal.docx' -o journal.md
以下是该命令的解释:
--extract-media=''
告诉 pandoc 从文件中提取图像.docx
并将它们放在默认子文件夹中(默认情况下名为“media”)。--wrap=preserve
告诉 pandoc 不要用换行符硬换行输出文件(这是默认设置)。下一个字段是输入文件名,-o
代表“输出”,因此journal.md
也是输出文件名。如果您不想拆分此文件(例如,如果您的选项卡仅包含一页),请跳至步骤 15。
(当您执行一系列这些操作时,您可以按↑(向上箭头)键来调用 shell 中的上一个命令,然后编辑文件名。)
创建一个新文件夹来存储选项卡中的页面。在此示例中,目前 OneNote 中日记选项卡中的所有页面都集中在 中
journal.md
。创建一个名为 的文件夹journal
,将最终分离的页面存储为单独的 .md 文件。如果文件中有任何图像
.docx
,这些图像将被导出到名为 的新文件夹media
中。将媒体文件夹(如果存在)拖到您刚刚创建的文件夹中。 (这就是为什么我们需要单独执行每个 pandoc 操作的原因,因为每次导出都会创建一个单独的媒体文件夹,我们希望将它们分开,以便 markdown 文件中的链接正常工作。我们可以编写一个巧妙的脚本来自动完成所有这些操作,但手动执行会花费更少的时间,除非您有大量的笔记本。)(注意:您可以通过将所需的文件夹名称放在参数的单引号中来节省一个步骤--extract-media=''
- 对于.docx
带有图像的文件,将自动为您创建一个文件夹。)打开 bash 终端并 cd 到包含该
.md
文件的目录。您在步骤 10 中创建的文件夹必须是此文件夹的子文件夹(除非您在以下命令中修复了路径)。如果还没有,请单击 Windows Bash 窗口图标,单击“属性”,选中“快速编辑模式”,然后单击“确定”。现在再次单击 Windows Bash 窗口图标,这次单击“默认值”,选中“快速编辑模式”,然后单击“确定”(这样您将来创建的新 Bash 窗口将记住此设置)。现在您可以在终端中选择文本并按Ctrl+C进行复制,或者右键单击终端窗口将文本粘贴到剪贴板中。现在我们可以在单独的位置准备命令,并将每个版本快速粘贴到 Bash 中。
自定义以下命令并对
.md
要拆分为单独页面的每个文件运行它:csplit ./journal.md --keep-files --prefix='journal/journalentry ' --suffix-format='%i.md' --elide-empty-files '/^\(Monday\|Tuesday\|Wednesday\|Thursday\|Friday\|Saturday\|Sunday\),/-2' '{*}'
(将其输入为一行。)
如你所见,
journal.md
是我们的 markdown 文件的名称(在当前目录中,用 表示./
),第二次出现的journal
(之后--prefix='
)是我们的子文件夹的名称,它将包含拆分文件,并且journalentry
是每个文件的命名(后跟索引号)。如果你想理解这个命令,这里有一个解释:
--keep-files
当遇到错误或文件结尾时仍然打印文件,确保最后一页将正确输出(因为它没有以我们的正则表达式的模式结尾)。--prefix
设置输出文件的命名方案。--suffix-format
允许我们设置文件扩展名(.md
在本例中),但我们必须包含%i
输出文件索引号的 sprintf 语句。--elide-empty-files
跳过输出我们不关心的空文件。最后,以 开头'/
和结尾的正则表达式/-2'
定义了何时拆分文件:它表示“当您在行首 (^) 找到 (/) 时(()星期一或(\|)星期二或星期三或星期四或星期五或星期六或星期日 ()) 后跟逗号,后退两行 (-2)”并在那里拆分文件,输出到目前为止的内容。最后一点,'{*}'
无限期地重复上一个命令,直到到达文件末尾。.docx
将和文件拖到.md
文件夹中,比如您现在创建的名为的文件夹intermediates
。或者您也可以直接删除它们。最好将它们保存一段时间,直到您熟悉新的文件格式,以防您想返回并参考转换过程中发生的事情。现在将它们移动到中间文件夹将避免我们忘记位置并重复步骤。.docx
对从 OneNote 导出的每个文件重复步骤 9-14 。.md
现在,每个选项卡都有一个文件夹,里面有一堆单独的文件,每个页面一个!此外,media
每个子文件夹中都有一个文件夹,其中包含 OneNote 选项卡中的图像。我建议将每个 OneNote 笔记本导出为一个
.mht
文件(单个文件网页),或者,如果你愿意的话,导出为一个.pdf
。这样,如果由于多次转换导致某些 Markdown 文件中的格式或其他信息丢失,你可以随时返回并轻松查看它在文件中的应有外观.mht
。此外,我建议将每个 OneNote 笔记本导出为一个.onepkg
文件(OneNote 包),这样,如果你想以原始文件格式在 OneNote 中重新打开笔记本(这可能很有用,例如,如果文件.mht
还缺少一些你想要恢复的原始格式)。完成每个笔记本后,右键单击 OneNote 中的笔记本,然后单击“关闭此笔记本”,这样您就不会意外编辑笔记本并不得不重新导出新的更改。对于 markdown 文件夹,我还为每个笔记本创建了一个文件夹,并将所有选项卡文件夹放在其中。
完成整个导出项目后,您可以转到 OneDrive 并删除所有已在那里同步的 OneNote 笔记本原件(当然,确保您现在备份了自己的文件!有适用于 Linux 的 OneDrive,或者您可以尝试 Syncthing 之类的程序)。
最后,我们可以使用两个脚本将所有 .md 文件重命名为其 OneNote 页面标题,即每个文件的第一行。制作以下文件:
文件 1:
~/scripts/rename-files-to-first-line.sh
for i in *md ; do mv -n "$i" "$(cat "$i"|head -n1|tr -d '\000-\037[]{}()/\?*')".md; done
文件 2:
~/scripts/recurse.sh
CDIR=$(pwd) for i in $(ls -R | grep :); do DIR=${i%:} # Strip ':' cd $DIR $1 # Your command cd $CDIR done
然后导航到您的笔记文件夹并
recurse.sh
使用该rename-files-to-first-line.sh
命令作为参数运行该命令:$ ~/scripts/recurse.sh ~/scripts/rename-files-to-first-line.sh
您将看到脚本递归地遍历所有文件,对第一行奇怪的文件(不会转换为文件名)和其他极端情况抛出一些错误。但是,命令
mv
中的命令rename-files-to-first-line
是使用参数执行的-n
,这将阻止它覆盖任何文件。可能有一些注释没有被重命名,因为其中的第一行是空白或其他奇怪的东西,但您可以手动修复这几个文件。享受从 OneNote 彻底解脱的乐趣。
注意事项:
这不会捕获子页面——如果愿意,您必须重新创建带有子子文件夹的页面。
我不知道它对表格的处理效果如何——无论如何,markdown 对表格来说有点笨拙。
可能还有其他类型的格式,例如字体,在导出时会丢失或出错。但对于富文本和图像,它效果很好!
答案2
另一个答案对我来说并不适用,因为我的笔记不是日记条目,但我找到了一个解决方案微软的 Graph API。这意味着您甚至不必运行 OneNote,只需要将您的笔记同步到您的 Microsoft 帐户,然后您就可以将您的笔记作为完美格式的 HTML(您可以在浏览器中查看或使用 Pandoc 转换为您喜欢的任何格式)。
魔法发生在这个 Python 脚本。它运行一个简单的本地 Web 服务器,您可以使用它登录到您的 Microsoft 帐户,一旦您执行此操作,它就会将您的所有笔记下载为 HTML,以及原始格式的图像和附件,并将它们存储在文件层次结构中,以保留笔记本的原始结构(包括页面顺序和子页面)。
在运行脚本之前,您必须在 Microsoft Azure 中注册一个“应用程序”,以便它可以访问 Graph API:
- 去https://aad.portal.azure.com/并使用您的 Microsoft 帐户登录。
- 选择“Azure Active Directory”,然后选择“管理”下的“应用程序注册”。
- 选择“新注册”。选择任意名称,将“支持的帐户类型”设置为“任何组织目录中的帐户和个人 Microsoft 帐户”,在“重定向 URI”下,选择 Web 并输入
http://localhost:5000/getToken
。注册。 - 复制“应用程序(客户端)ID”并将其粘贴到
client_id
Python 脚本的开头。 - 选择“管理”下的“证书和机密”。按“新客户端机密”,选择一个名称并确认。
- 复制客户端机密并将其粘贴为
secret
Python 脚本中的内容。 - 选择“管理”下的“API 权限”。按“添加权限”,向下滚动并选择 OneNote,选择“委派权限”,然后勾选“Notes.Read”和“Notes.Read.All”。按“添加权限”。
然后你需要安装 Python 依赖项。确保已安装 Python 3.7(或更新版本),然后使用命令安装依赖项pip install flask msal requests_oauthlib
。
现在您可以运行该脚本。在终端中,导航到脚本所在的目录并使用 运行它python onenote_export.py
。这将在端口 5000 上启动本地 Web 服务器。
在浏览器中导航至http://本地主机:5000并登录到您的 Microsoft 帐户。第一次执行此操作时,您还必须接受该应用程序可以读取您的 OneNote 笔记。(这不会让任何第三方访问您的数据,只要您不共享在 Azure 门户上创建的客户端 ID 和密钥)。此后,返回终端以跟踪进度。
注意:Microsoft 限制了您在给定时间段内可以执行的请求数。因此,如果您有很多笔记,您最终可能会在终端中看到这样的消息:Too many requests, waiting 20s and trying again.
这不是问题,但这意味着整个过程可能需要一段时间。此外,登录会话可能会在一段时间后过期,从而导致TokenExpiredError
。如果发生这种情况,只需重新加载http://本地主机:5000脚本将继续运行(跳过已下载的文件)。
答案3
答案4
我开发了一个 Windows 控制台应用程序,可以以 markdown 格式导出 OneNote 笔记本。你可以在这里查看:https://github.com/alxnbl/onenote-md-exporter。
希望能够帮到你。