[Shell]Cleanly split large Inbox file
wolfen
-
wolfen13fr Posted messages 1 Status Member -
wolfen13fr Posted messages 1 Status Member -
Hello,
Regularly, we have users who let their Inbox file in Thunderbird "inflate" and it then reaches the limit of 4GB!
The solution I have found so far is to manually split the file into several files of 1,000,000 lines (about 740 MB per file) and then combine the end of the first file with the beginning of the second to reconstitute the last email of the split file, the end of the second with the beginning of the third, and so on...
I think it is feasible to script all this in shell.
I already know how to split my file into several parts:
With that, I get 6 files named "archiveaa", "archiveab", ... "archiveaf".
This part is simple... However, for the adjustment, I’m not quite sure how to proceed.
I know that a message in an Inbox file starts with the pattern "From - ". But how can I tell the script to take the last occurrence of this pattern, cut what follows, and paste it at the beginning of the next file to reconstitute the message? I’m stuck here.
Should I use sed or awk? Does anyone have a lead for the second part?
Thank you in advance!
Regularly, we have users who let their Inbox file in Thunderbird "inflate" and it then reaches the limit of 4GB!
The solution I have found so far is to manually split the file into several files of 1,000,000 lines (about 740 MB per file) and then combine the end of the first file with the beginning of the second to reconstitute the last email of the split file, the end of the second with the beginning of the third, and so on...
I think it is feasible to script all this in shell.
I already know how to split my file into several parts:
split -1000000 Inbox archive
With that, I get 6 files named "archiveaa", "archiveab", ... "archiveaf".
This part is simple... However, for the adjustment, I’m not quite sure how to proceed.
I know that a message in an Inbox file starts with the pattern "From - ". But how can I tell the script to take the last occurrence of this pattern, cut what follows, and paste it at the beginning of the next file to reconstitute the message? I’m stuck here.
Should I use sed or awk? Does anyone have a lead for the second part?
Thank you in advance!
2 answers
-
I answer myself, after two days of research and tinkering ...
Here is a somewhat convoluted script that works on Linux (Ubuntu 10.04 LTS):
#!/bin/sh # shell script "decoupagembox.sh" version Linux - Ubuntu 10.04 LTS # # This script splits an mbox format file into multiple archives. # The number of emails per archive is configurable. The size of each archive # will depend on the weight of the emails and thus the attachments linked. # February 2011 # code under Creative Commons by-nc-sa license (free distribution and modification # by citing the original author and without commercial use # # author: Damien MAURAN, # dmauran@gmail.com echo "Splitting an mbox format file into multiple archives ..." echo if test "$1" = "" then echo "Please indicate the name of the file to process, the number of emails per archive" echo "and the destination path. Example:" echo echo "decoupagembox.sh source_file_name xx destination_path/" echo echo "where xx is the number of emails per archive. If xx is not indicated," echo "the default value will be 500 emails per archive." echo echo "End of the script ... no processing done." exit 0 fi if test "$3" = "" then echo "Please indicate the name of the file to process, the number of emails per archive" echo "and the destination path. Example:" echo echo "decoupage.sh file_name xx destination_path/" echo echo "where xx is the number of emails per archive. If xx is not indicated," echo "the default value will be 500 emails per archive." echo echo "End of the script ... no processing done." exit 0 fi if test "$2" = "" then X=$((500)) else X=$(($2)) fi start_date=$(date) echo "** Start of processing: $start_date **" echo echo "isolating emails: 1 email = 1 file" echo echo "Please wait, this may take time ..." echo awk '/From - /{n++}{print >"/tmp/mboxout" n ".txt" }' $1 ls /tmp/mboxout*.txt | wc -l > counter.txt nb='cat counter.txt' rm counter.txt number=$(($nb)) echo "Number of extracted emails: $number" counter1=$(($nb/$X)) echo "Number of packets of $X emails: $counter1 packets + 1 packet of remaining emails" echo echo "Grouping emails to create archives" echo echo "Please wait ..." echo counter2=$((counter1+1)) for i in $(seq 0 1 $counter2) do nb_file=$(($i*$X)); end_file=$(($nb_file+$X)); for j in $(seq $nb_file 1 $end_file) do if test -f "/tmp/mboxout$j.txt" then cat /tmp/mboxout$j.txt >> archive$i; fi done; done rm /tmp/mboxout*.txt echo "The following archive files have been created:" ls -x archive* echo mv archive* $3 echo "They have been saved in: $3/" echo end_date=$(date) echo "** end of processing: $end_date **" exit 0
And just in case, here is the same code but optimized for Mac OS X (version 10.6.5):#!/bin/sh # shell script "decoupagembox.sh" version Mac OS X (version 10.6.5) # # This script splits an mbox format file into multiple archives. # The number of emails per archive is configurable. The size of each archive # will depend on the weight of the emails and thus the attachments linked. # February 2011 # code under Creative Commons by-nc-sa license (free distribution and modification # by citing the original author and without commercial use # # author: Damien MAURAN, # dmauran@gmail.com echo "Splitting an mbox format file into multiple archives ..." echo if test "$1" = "" then echo "Please indicate the name of the file to process, the number of emails per archive" echo "and the destination path. Example:" echo echo "decoupage.sh file_name xx destination_path/" echo echo "where xx is the number of emails per archive. If xx is not indicated," echo "the default value will be 500 emails per archive." echo echo "End of the script ... no processing done." exit 0 fi if test "$3" = "" then echo "Please indicate the name of the file to process, the number of emails per archive" echo "and the destination path. Example:" echo echo "decoupage.sh file_name xx destination_path/" echo echo "where xx is the number of emails per archive. If xx is not indicated," echo "the default value will be 500 emails per archive." echo echo "End of the script ... no processing done." exit 0 fi if test "$2" = "" then X=$((500)) else X=$(($2)) fi start_date=$(date) echo "** Start of processing: $start_date **" echo echo "isolating emails: 1 email = 1 file" echo echo "Please wait, this may take time ..." echo awk '/From - /{n++}{filename = "/tmp/mboxout"n".txt"; print >> filename;close (filename) }' $1 ls /tmp/mboxout*.txt | wc -l > counter.txt nb='cat counter.txt' rm counter.txt number=$(($nb)) echo "Number of extracted emails: $number" counter1=$(($nb/$X)) echo "Number of packets of $X emails: $counter1 packets + 1 packet of remaining emails" echo echo "Grouping emails to create archives" echo echo "Please wait ..." echo counter2=$((counter1+1)) i=$((0)) while [ $i -lt $counter2 ] do nb_file=$(($i*$X)); end_file=$(($nb_file+$X)); j=$(($nb_file)) while [ $j -lt $end_file ] do if test -f "/tmp/mboxout$j.txt" then cat /tmp/mboxout$j.txt >> archive$i; fi true $((j++)) done; true $((i++)) done rm /tmp/mboxout*.txt echo "The following archive files have been created:" ls -x archive* echo mv archive* $3 echo "They have been saved in: $3/" echo end_date=$(date) echo "** end of processing: $end_date **" exit 0 -
I answer myself, after two days of research and tinkering...
Here is a somewhat convoluted script but which works under Linux (Ubuntu 10.04 LTS):
#!/bin/sh
# shell script "decoupagembox.sh" version Linux - Ubuntu 10.04 LTS
#
# This script splits a file in mbox format into several archives.
# The number of emails per archive is adjustable. The size of each archive
# will depend on the weight of emails and thus the attachments related.
# February 2011
# code under Creative Commons by-nc-sa license (free distribution and modification
# by citing the original author and without commercial use
#
# author: Damien MAURAN,
echo "Splitting a mbox format file into several archives ..."
echo
if test "$1" = ""
then echo "Please provide the name of the file to process, the number of emails per archive"
echo "and the destination path. Example:"
echo
echo "decoupagembox.sh source_file_name xx destination_path/"
echo
echo "where xx is the number of emails per archive. If xx is not specified,"
echo "the default value will be 500 emails per archive."
echo
echo "End of script ... no processing done."
exit 0
fi
if test "$3" = ""
then echo "Please provide the name of the file to process, the number of emails per archive"
echo "and the destination path. Example:"
echo
echo "decoupage.sh file_name xx destination_path/"
echo
echo "where xx is the number of emails per archive. If xx is not specified,"
echo "the default value will be 500 emails per archive."
echo
echo "End of script ... no processing done."
exit 0
fi
if test "$2" = ""
then X=$((500))
else
X=$(($2))
fi
start_date=$(date)
echo "** Start of processing: $start_date **"
echo
echo "isolation of emails: 1 email = 1 file"
echo
echo "Please wait, this may take some time..."
echo
awk '/From - /{n++}{print >"/tmp/mboxout" n ".txt" }' $1
ls /tmp/mboxout*.txt | wc -l > count.txt
nb='cat count.txt'
rm count.txt
number=$(($nb))
echo "Number of extracted emails: $number"
count1=$(($nb/$X))
echo "Number of packages of $X emails: $count1 packages + 1 package of remaining emails"
echo
echo "Grouping emails to create archives"
echo
echo "Please wait..."
echo
count2=$((count1+1))
for i in $(seq 0 1 $count2)
do
nb_file=$(($i*$X));
end_file=$(($nb_file+$X));
for j in $(seq $nb_file 1 $end_file)
do
if test -f "/tmp/mboxout$j.txt"
then cat /tmp/mboxout$j.txt >> archive$i;
fi
done;
done
rm /tmp/mboxout*.txt
echo "The following archive files have been created:"
ls -x archive*
echo
mv archive* $3
echo "They have been saved in: $3/"
echo
end_date=$(date)
echo "** end of processing: $end_date **"
exit 0
And just in case, here's the same code but optimized for Mac OS X (version 10.6.5):
#!/bin/sh
# shell script "decoupagembox.sh" version Mac OS X (version 10.6.5)
#
# This script splits a file in mbox format into several archives.
# The number of emails per archive is adjustable. The size of each archive
# will depend on the weight of emails and thus the attachments related.
# February 2011
# code under Creative Commons by-nc-sa license (free distribution and modification
# by citing the original author and without commercial use
#
# author: Damien MAURAN,
# dmauran@gmail.com
echo "Splitting a mbox format file into several archives ..."
echo
if test "$1" = ""
then echo "Please provide the name of the file to process, the number of emails per archive"
echo "and the destination path. Example:"
echo
echo "decoupage.sh file_name xx destination_path/"
echo
echo "where xx is the number of emails per archive. If xx is not specified,"
echo "the default value will be 500 emails per archive."
echo
echo "End of script ... no processing done."
exit 0
fi
if test "$3" = ""
then echo "Please provide the name of the file to process, the number of emails per archive"
echo "and the destination path. Example:"
echo
echo "decoupage.sh file_name xx destination_path/"
echo
echo "where xx is the number of emails per archive. If xx is not specified,"
echo "the default value will be 500 emails per archive."
echo
echo "End of script ... no processing done."
exit 0
fi
if test "$2" = ""
then X=$((500))
else
X=$(($2))
fi
start_date=$(date)
echo "** Start of processing: $start_date **"
echo
echo "isolation of emails: 1 email = 1 file"
echo
echo "Please wait, this may take some time..."
echo
awk '/From - /{n++}{filename = "/tmp/mboxout"n".txt"; print >> filename;close (filename) }' $1
ls /tmp/mboxout*.txt | wc -l > count.txt
nb='cat count.txt'
rm count.txt
number=$(($nb))
echo "Number of extracted emails: $number"
count1=$(($nb/$X))
echo "Number of packages of $X emails: $count1 packages + 1 package of remaining emails"
echo
echo "Grouping emails to create archives"
echo
echo "Please wait..."
echo
count2=$((count1+1))
i=$((0))
while [ $i -lt $count2 ]
do
nb_file=$(($i*$X));
end_file=$(($nb_file+$X));
j=$(($nb_file))
while [ $j -lt $end_file ]
do
if test -f "/tmp/mboxout$j.txt"
then cat /tmp/mboxout$j.txt >> archive$i;
fi
true $((j++))
done;
true $((i++))
done
rm /tmp/mboxout*.txt
echo "The following archive files have been created:"
ls -x archive*
echo
mv archive* $3
echo "They have been saved in: $3/"
echo
end_date=$(date)
echo "** end of processing: $end_date **"
exit 0