Combine splitted low & high byte files into one file

Hi all,

i have a binary file splitted into 2 chunks, first part with all high bytes and the second part with all low bytes.
I need to combine the two chunks into one binary file like (eg. exactly the reverse of the splitting method solved in the thread # 130940)

Hi bytes file content:
0000000     0   2   4   6   8  10  12  14  16  18  20  22  24  26  28  30 
0000020    32  34  36  38  40  42  44  46  48  50  52  54  56  58  60  62 
0000040  

Lo bytes file content: 
0000000     1   3   5   7   9  11  13  15  17  19  21  23  25  27  29  31 
0000020    33  35  37  39  41  43  45  47  49  51  53  55  57  59  61  63 
0000040

Expected result: 
0000000     0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15 
0000020    16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31 
0000040    32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47 
0000060    48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63 
0000100 

Please help me to develop the combining script!

Thanks
mzs

for gnu flavor awk, try:

awk '
NR==1 {f=NF}
{for (i=2; i<=NF; i++) a[c++]=$i}
END {
 asort(a);
 printf "%07d", d;
 for (i=1; i<=c; i++) {
    printf "%6d", a;
    if (!(i % (f-1))) {printf "\n%07d", d += 20}
 }
 if (!(i % (f-1))) {printf "\n%07d\n", (d += 20)} else {print ""};
}
' h_byte l_byte

Try one more Awk version

$ cat file1
0000000     0   2   4   6   8  10  12  14  16  18  20  22  24  26  28  30 
0000020    32  34  36  38  40  42  44  46  48  50  52  54  56  58  60  62 
0000040 
$ cat file2
0000000     1   3   5   7   9  11  13  15  17  19  21  23  25  27  29  31 
0000020    33  35  37  39  41  43  45  47  49  51  53  55  57  59  61  63 
0000040
awk 'NR==FNR{
                  for(i=2;i<=NF;i++)
                  A[$1]=(i==2)?$i FS : A[$1] FS $i
                  next
            }

  ($1 in A){
            split(A[$1],Ar,FS)
        
            for(i=2;i<=NF;i++){
                                 printf (i==2)? !x ? sprintf("%07d",x) OFS Ar[i-1] OFS $i : \
                                 sprintf("%07d",x+=20) OFS Ar[i-1] OFS $i : \
                                 (i==10)? RS sprintf("%07d",x+=20) OFS Ar[i-1] OFS $i : \
                                 OFS Ar[i-1] OFS $i 
                              }
            printf RS
           }'   file1 file2    

OR

awk '{
        for(i=2;i<=NF;i++)
        A[++n]=$i
     }

  END{
           asort(A)
           for(i=1;i<=length(A);i++){
                                         LFS = (i%16==0) ? RS sprintf("%07d",x+=20) OFS: OFS 
                                         printf (i==1)? sprintf("%07d",x) LFS A LFS : A LFS
                                    }        
           
     }' file1 file2

Resulting

0000000 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0000020 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0000040 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
0000060 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

I believe you both misunderstood. The task is to combine two binary files into a new binary file. The sample data in the OP are dumps of the actual data, not the actual data itself.

The od -like output that your solutions produce would require further processing to generate the desired binary output.

Regards,
Alister

How about using perl:

#!/usr/bin/perl -w

open HI, $ARGV[0] || die $!;
binmode HI;
open LO, $ARGV[1] || die $!;
binmode LO;

my $hidata;
my $lowdata;

while (read(HI, $hidata, 1)) {

   read(LO, $lowdata, 1) || last;

   printf "%c%c", ord($hidata),ord($lowdata);
}
close HI;
close LO;

Eg:

$ printf "\x0\x2\x4\x6\x8\xA" > Hi
$ printf "\x1\x3\x5\x7\x9\xB" > Lo
$ ./ans.pl Hi Lo > result
$ od -t d1 result
0000000    0    1    2    3    4    5    6    7    8    9   10   11
0000014
1 Like

@ alister you might be right.. I am not sure.. I thought this could be text file.

-A@

As a shell script you could try this:

#!/bin/bash

exec 3< $1
exec 4< $2

while IFS= read -N 1 -sru 3 Hi
do
   IFS= read -N 1 -sru 4 Lo || break
   [ ${#Hi} -eq 0 ] && printf "\x0" || printf "%s" "$Hi"
   [ ${#Lo} -eq 0 ] && printf "\x0" || printf "%s" "$Lo"
done

exec 3>&-
exec 4>&-

Eg:

$ ./ans.sh Hi Lo > result
$ od -t d1 result
0000000    0    1    2    3    4    5    6    7    8    9   10   11
0000014
export LC_CTYPE=C
dump() { od -An -vtu1 "$1" | tr -c 0-9 \\n; }
paste -d \\n <(dump hi) <(dump lo) | awk 'NF {printf "%c",$0}' > newbin

Regards,
Alister

---------- Post updated at 06:29 PM ---------- Previous update was at 06:07 PM ----------

That's not quite correct. read -N (and read -n ) deal with characters. When dealing with binaries, you must work with bytes. Your solution is at the mercy of the current locale.

You need to explicitly specify a single-byte character locale, such as with LC_CTYPE=C (or LC_CTYPE=POSIX ).

Regards,
Alister

---------- Post updated at 06:51 PM ---------- Previous update was at 06:29 PM ----------

Looking at my (years old) post in the thread referenced by the OP, I see a couple of bugs:

od -An -vtd1 file | tr -cs '0-9' '\n' | awk 'NF{printf("%c",$0) > (++i%2?"hi":"lo")}'

(1) od is using a signed format when it must be unsigned, and (2) the AWK command's output depends on locale. Both are fixed in this post's recommendation.

Live and learn. :slight_smile:

Regards,
Alister