如何使用终端将一个mbox文件分割成大小为n MB的块?

13

我看了这个SO上的问题,但它并不能完全帮助我。我想将由Gmail生成的mbox文件导入到另一个网络邮件服务中,但问题是它每次只允许导入40MB大小的文件。

所以我需要将mbox文件分成最多40MB大小的文件,然后再逐个导入。你会如何做到呢?

我的初始想法是使用另一个脚本(formail)将每个邮件保存为单独的文件,然后运行一个脚本将它们组合成40 MB大的文件,但我仍然不知道如何在终端上完成这个过程。

我也看了split命令,但我担心它会截断邮件。 感谢任何帮助!

5个回答

18

我刚刚改进了一个脚本,基于Mark Sechell的回答。我们可以看到,那个脚本可以根据每个块中的邮件数量来解析mbox文件。这个改进后的脚本可以根据每个块的定义的最大尺寸来解析mbox文件。
因此,如果您在上传或导入mbox文件时有大小限制,您可以尝试使用下面的脚本将mbox文件分成指定大小的块。
请将下面的脚本保存到一个文本文件中,例如mboxsplit.txt,保存到包含mbox文件(例如命名为mbox)的目录中:

BEGIN{chunk=0;filesize=0;}
    /^From /{
    if(filesize>=40000000){#file size per chunk in byte
        close("chunk_" chunk ".txt");
        filesize=0;
        chunk++;
    }
  }
  {filesize+=length()}
  {print > ("chunk_" chunk ".txt")}

然后在包含mboxsplit.txtmbox文件的目录中运行/键入以下命令:

  awk -f mboxsplit.txt mbox

请注意

  • 结果的大小可能会大于定义的大小。这取决于在检查块大小之前将最后一个电子邮件大小插入缓冲区/块。
  • 它不会拆分电子邮件正文。
  • 如果电子邮件大小大于指定的块大小,则一个块可能只包含一个电子邮件。

我建议您将块大小指定为小于或低于最大上传/导入大小。


如果我使用这个,有没有一种方法可以重新组合分割的文件?谢谢。 - Ycon
当然可以将它们组合在一起!请记住,拆分文件是文本文件,可以简单地组合在一起。 - Oki Erie Rinaldi
1
非常好的回答。而且速度也很快。 - jangeador
3
可考虑改进的方法是:使用sprintf函数对文件名索引进行零填充。类似这样的写法:{print > ("chunk_" sprintf("%03d",chunk) ".txt");} - Sojoodi
第二个 @Sojoodi 的评论。楼主应该修改原始脚本或在答案中提到这种修改。 - siliconpi
显示剩余2条评论

15
如果您的mbox处于标准格式,则每个消息将以From和一个空格开头:
From someone@somewhere.com

那么,您可以将您的MBOX文件复制到一个临时目录,并尝试使用awk逐条处理它,仅在每个消息的开头进行分割。假设我们选择每个输出文件包含1,000条消息:

COPY YOUR MBOX TO A TEMPORARY DIRECTORY -> 将您的MBOX文件复制到一个临时目录 awk -> awk -> 逐条地 -> 仅在每个消息的开头进行分割 -> 假设我们为每个输出文件选择了1,000条消息:
awk 'BEGIN{chunk=0} /^From /{msgs++;if(msgs==1000){msgs=0;chunk++}}{print > "chunk_" chunk ".txt"}' mbox

那么你将会得到输出文件,分别叫做chunk_1.txtchunk_n.txt,每个文件最多包含1,000条消息。

如果你很不幸地在使用Windows(它无法理解单引号),你需要将以下内容保存到一个名为awk.txt的文件中:

BEGIN{chunk=0} /^From /{msgs++;if(msgs==1000){msgs=0;chunk++}}{print > "chunk_" chunk ".txt"}

然后输入

awk -f awk.txt mbox

尝试使用10,000条消息,如果文件太大,请删除'chunk'文件并将10,000增加到20,000,然后再次运行。这不是科学的,但我猜你不必每天都这样做,所以可能需要进行一些实验。 - Mark Setchell
我可以直接在控制台中运行吗?而 mbox 是文件 URL 吗? - Alex
1
我已经简化了它 - 只需将一行复制并粘贴到终端中,然后按“Enter”键。 - Mark Setchell
2
不行,错误还是一样的:awk: illegal statement at source line 1。我甚至开始编辑你的答案,以确保我没有复制不想要的字符。似乎有些地方出了问题。我不知道,但对我来说,print > "chunk_" chunk ".txt" 看起来有点奇怪,这是正确的语法吗? - Alex
@Ycon 当然可以,只需循环遍历所有块,并使用 cat 将它们附加到一个新的 mbox 文件中即可。 - Mark Setchell
显示剩余12条评论

3
formail非常适合这个任务。你可以查看formail的+skip-total选项。
选项 ... +skip 在拆分时跳过前skip封邮件。 -total 在拆分时最多输出total封邮件。
根据您的邮箱和邮件大小,您可以尝试使用此方法。
formail -100 -s <google.mbox >import-01.mbox
formail +100 -100 -s <google.mbox >import-02.mbox
formail +200 -100 -s <google.mbox >import-03.mbox

最初的回答:
当然,这些部分不一定需要是相等大小的。如果有一封大邮件,你可能只需要使用formail +100 -60 -s <google.mbox >import-02.mbox,或者如果有许多小邮件,则可以使用formail +100 -500 -s <google.mbox >import-02.mbox
要查找每个块的初始邮件数量,请尝试:

etc.

formail -100 -s <google.mbox | wc
formail -500 -s <google.mbox | wc
formail -1000 -s <google.mbox | wc

你可能需要进行一些实验,以适应你的邮箱大小。另一方面,由于这似乎是一次性任务,你可能不想花太多时间在这上面。

原始回答:Original Answer


0
我在尝试将来自Gmail的MBOX文件导入Thunderbird(在Windows上)时遇到了这个问题。ImportExporttools告诉我文件大小超过2GB并停止了导入。
解决方案出奇地简单,因为Thunderbird本身使用MBOX文件作为本地邮件存储。
  1. 在Thunderbird中创建一个新的本地文件夹(例如"Import"),然后关闭Thunderbird
  2. 找到Thunderbird的邮件文件夹,例如C:\Users\uf501ap\AppData\Roaming\Thunderbird\Profiles\xyz.default-release\Mail\Local Folders
  3. 将空文件替换为您新创建的文件夹中的MBOX文件(在此示例中为"Import")
  4. 打开Thunderbird并在新创建的文件夹中找到邮件。Thunderbird将开始索引文件,并在一分钟左右显示MBOX文件中包含的邮件。

0
我的初步想法是使用另一个脚本(formail)将每个邮件保存为单个文件,然后运行一个脚本将它们合并成40 MB的大文件,但我仍然不知道如何在终端中执行此操作。
如果我理解你的意思正确,你想将文件拆分,然后在导入之前将它们合并成一个大文件。这听起来像是split和cat的用途。Split根据您的大小规格(基于行或字节)拆分文件。然后它会添加一个后缀来保持这些文件的顺序,然后您可以使用cat将这些文件组合在一起:
$ split -b40m -a5 mbox  # this makes mbox.aaaaa, mbox.aaab, etc.

一旦您在其他系统上获取了文件:

$ cat mbox.* > mbox

如果您想要避免信息被分割在不同的文件中,因为您需要逐个导入每个文件到新的邮件系统中,所以最好不要这样做。

不太对,我认为formail是将每封电子邮件导出到自己的文本文件中,并从中创建大约<40 MB的块的好主意,以便我可以导入它们。因为分割可能会在电子邮件正中间拆分文件,导致无法正确导入。 - Alex
Split将电子邮件拆分为两个单独的文件。但是,您似乎在导入之前重新组合了这些文件。如果是这种情况,那么split拆分单个电子邮件并不重要,因为cat会将它们拼接在一起。split总是按行拆分。 - David W.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接