Split large file into smaller files without disturbing the entry chunks

Dears,

 Need you help with the below file manipulation. I want to split the file into 8 smaller files but without cutting/disturbing the entries \(meaning every small file should start with a entry and end with an empty line\). It will be helpful if you can provide a one liner command for this and also help me understand the command u give. I'm not very good at this.

Input_file:- (With more than 10 Million such chunks separated by empty line)

dn: MSISDN=asdasdasdasd,dc=msisdn,ou=identities,dc=ppp
objectClass: alias
objectClass: MSISDN
MSISDN: asdasdasdasd
aliasedObjectName: mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp

dn: IMSI=uuuuuuuuuu,dc=imsi,ou=identities,dc=ppp
objectClass: alias
objectClass: IMSI
IMSI: uuuuuuuuuuu
aliasedObjectName: mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp

dn: mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp
mscId: asdasdasdasdaaaaaaa4
DSUnitGroup: 1
objectClass: CUDBMultiServiceConsumer

dn: serv=AAA,mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp
objectClass: CUDBService
serv: AAA

dn: serv=Auth,mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp
objectClass: CUDBService
serv: Auth

dn: IMSI=426019001711473,serv=Auth,mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp
AMFVALUE: 15
EKI::
objectClass: 
BNS: 15
GAPSIGN: 15
MIGRATIONEXPDATE:: 
SQNPS: 
KIND: 
MIGRATIONSTEP: 
FSETIND: 
AKAALGIND: 
GAP:: 
CDC: 0
SQN: 15
IMSI: 
A3A8IND: 0
SQNCS: 15
AKATYPE: 0
VNUMBER: 0
SQNIMS: 15
A4IND: 0

small_file1:-

dn: MSISDN=asdasdasdasd,dc=msisdn,ou=identities,dc=ppp
objectClass: alias
objectClass: MSISDN
MSISDN: asdasdasdasd
aliasedObjectName: mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp

dn: IMSI=uuuuuuuuuu,dc=imsi,ou=identities,dc=ppp
objectClass: alias
objectClass: IMSI
IMSI: uuuuuuuuuuu
aliasedObjectName: mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp

dn: mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp
mscId: asdasdasdasdaaaaaaa4
DSUnitGroup: 1
objectClass: CUDBMultiServiceConsumer

dn: serv=AAA,mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp
objectClass: CUDBService
serv: AAA

small_file2:-

dn: serv=Auth,mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp
objectClass: CUDBService
serv: Auth

dn: IMSI=426019001711473,serv=Auth,mscId=asdasdasdasdaaaaaaa4,ou=multiSCs,dc=ppp
AMFVALUE: 15
EKI::
objectClass: 
BNS: 15
GAPSIGN: 15
MIGRATIONEXPDATE:: 
SQNPS: 
KIND: 
MIGRATIONSTEP: 
FSETIND: 
AKAALGIND: 
GAP:: 
CDC: 0
SQN: 15
IMSI: 
A3A8IND: 0
SQNCS: 15
AKATYPE: 0
VNUMBER: 0
SQNIMS: 15
A4IND: 0

Thank you in advance.
Kamesh G

awk -v c=8 '{if(f) close(f);f=(FILENAME "_" FNR%c);print $0 ORS >>f}' RS= myFile

@vgersh99, it worked, thank you for the help.

the problem is the file split part is okay but the contents are not as expected, can you help with the command to create the output like sample_file1 and sample_file2 examples.

right now my files are getting split but the expected result is to be each file should begin with the start of smaller chunk eg: the line start with dn: should be the start of each smaller files.

You now see how important it is to exercise due care when

  • phrasing your request
  • formatting your post

vgersh99's proposal fulfills your request in post#1 (given that the split into file1 and file2 was hidden invisibly somewhere in your text and overlooked by the mod who inserted the necessary code tags for you) , and even does so for your post#3 as every file produced starts with dn: . How to define the optimal position of a file break?

Would this paraphrase of the specification come close to what you need:
Split the file into n contiguous chunks on record boundaries while keeping the original order and togetherness of the records?

@Rudic, sorry that my post was misleading. Are you right, the input file should be split into 8 smaller files also maintaining the integrity of each chunk of lines in the input file.

-> Each of the 8 smaller output files should start with dn: and end with an empty line.
-> optimal position of a file break, It should be the "empty line" that is separating the input file chunks. the expected it to have the input file split into 8 smaller files without disturbing the order/integrity of each chunks.

Hmmm... I guess we'd need a descriptive definition of how the file should be split.
Each record/block starts with dn:
What logic did you use to split your sample file into 2 files you provided?
What decision did you make to start outputting chunks into small_file2?

The sample I printed above was just an example I did manually in a text editor. I'm on a very armature level I was trying to split the file based on number of lines and split command but then it doesn't help in the expected output of each small file starting with a dn: and end with an empty line. I was hoping the forum can help.

Understood, but we can only help if you provide a detailed description of how the splitting should be done.
Without that I don't think it's worth starting guessing...
Can you come up with the better description - it's "bit" too nebulous now..

@vgersh99 - I really appreciate all the help, just want to ask one more thing.

Say my input file looks like below.
dn: serv=AAA,mscId=aaaaaa002aaaaaaaa426019001711495,ou=multiSCs,dc=btc
objectClass: CUDBService
serv: AAA

dn: serv=AAA,mscId=aaaaaa002aaaaaaaa426019001711250,ou=multiSCs,dc=btc
objectClass: CUDBService
serv: AAA

dn: serv=AAA,mscId=aaaaaa002aaaaaaaa426019001713072,ou=multiSCs,dc=btc
objectClass: CUDBService
serv: AAA

dn: serv=AAA,mscId=aaaaaa002aaaaaaaa426019001713017,ou=multiSCs,dc=btc
objectClass: CUDBService
serv: AAA

dn: serv=AAA,mscId=aaaaaa002aaaaaaaa426019001712815,ou=multiSCs,dc=btc
objectClass: CUDBService
serv: AAA

and i want to split the file into smaller 8 files, and all the above chunks of information starting with "dn: serv=AAA,mscId=" and seperated by a empty line. Is it possible to split time to smaller files such that each small file will have the entry starting with "dn: serv=AAA,mscId=" and end with an empty line, without disturbing the order/integrity of the input entries. (One liner command needed)

Kindly also explain the command interms of who the file manipulations is happening.

Thanks in advance.

Something along this line?

awk  '
NR == 1 {("stat -c%s " FILENAME) | getline SZ
         SZ /= 8
         FN  = FILENAME "_" ++c;
        }

        {if (CNT > SZ)  {if (FN) close(FN)
                         FN  = FILENAME "_" ++c;
                         CNT = 0
                        }
         CNT += length
         print $0 ORS  >  FN
        }
' RS= file

RudiC thank you. I will try this I don't have the access to the server now. I will try this. Thank you again

---------- Post updated 04-29-18 at 08:37 AM ---------- Previous update was 04-28-18 at 09:12 AM ----------

@RudiC - the script worked perfectly, thank you :slight_smile:

Can Someone help me in Understanding the below lines please???

    awk  '
    NR == 1 {("stat -c%s " FILENAME) | getline SZ
             SZ /= 8
             FN  = FILENAME "_" ++c;
            }
    
            {if (CNT > SZ)  {if (FN) close(FN)
                             FN  = FILENAME "_" ++c;
                             CNT = 0
                            }
             CNT += length
             print $0 ORS  >  FN
            }
    ' RS= mscId_PL_multiSCs.ldif

Thanks in advance.

awk '
NR == 1 {("stat -c%s " FILENAME) | getline SZ           # right at the start: read file size into SZ variable
         SZ /= 8                                        # calculate chunk size
         FN = FILENAME "_" ++c;                         # determine first output file name
        }

        {if (CNT > SZ)  {if (FN) close(FN)              # if chunk size reached: close old file
                         FN  = FILENAME "_" ++c;        # determine next output file name
                         CNT = 0                        # reset size count
                        }
         CNT += length                                  # sum up line lengths into CNT
         print $0 ORS > FN                              # print line to output file incl. empty line
        }
' RS= file                                              # empty record separator means: empty line, i.e.
                                                        # double line feed, is a record separator