I need get checksum Adler32 and store to variable in bash. It will be used in automatic script and it will be useful if no additional app/liberty will used which user need to install. Is it possible to use common / basic command Bash command to get this value?
CodePudding user response:
This is monumentally slow (about 60,000 times slower than C), but it shows that yes, it is possible.
#!/bin/bash
sum1=1
sum2=0
while LANG=C IFS= read -r -d '' -n 1 ch; do
printf -v val '%d\n' "'$ch"
(( val = val < 0 ? val 256 : val, sum1 = (sum1 val) % 65521, sum2 = (sum2 sum1) % 65521 ))
done
(( adler = sum1 65536 * sum2 ))
echo $adler
Hopefully someone who actually knows bash could vastly improve on this.
CodePudding user response:
Maybe this solution?:
python -c "import zlib; print(zlib.adler32(\"${file}\"))"
CodePudding user response:
Tried two adler bash functions one with an ordination dictionary and one with printf also tried some bit shifting like instead of sum1=(sum1 val)e521 -> temp= (sum1 val),sum1=temp >> 16 *15 (temp & 65355)e521 wasn't able to improve it a lot, perhaps somebody knows a faster one.
last function is a awk function, it is the fastest, works also on files.
#!/bin/bash
a=$'Hello World'; b=""
for ((i=0;i<1000;i )); do b =$a; done
#-- building associative array ord byte character array
declare -Ai ordCHAR=()
for ((i=1;i<256;i )); do printf -v hex "%x" $i; printf -v char "\x"$hex; ordCHAR[$char]=$i; done
unset hex char i
#-- building associative array ord byte character array -- END
#-- with dictionary
function adler32_A ()
{
local char; local -i sum1=1 sum2=0 val
LC_ALL=C; while read -rN 1 char; do
val=${ordCHAR[$char]};
((sum1=(sum1 val) % 65521, sum2 = (sum2 sum1) % 65521 ))
done <<< $1
#-- removing 0A=\n addition, because of here string
(( sum2-=sum1, sum2<0 ? sum2 =65521 :0, sum1-=val, sum1<0 ? sum1 =65521 :0 ));
printf "x" $(( (sum2 << 16) sum1 ))
LC_ALL=""
}
#-- with printf
function adler32_B ()
{
local char; local -i sum1=1 sum2=0 val
LC_ALL=C; while read -rN 1 char;
do
printf -v val '%d' "'$char"
(( sum1 = (sum1 val) % 65521, sum2 = (sum2 sum1) % 65521 ))
done <<< $1
#-- removing 0A=\n addition, because of here string
(( sum2-=sum1, sum2<0 ? sum2 =65521 :0, sum1-=val, sum1<0 ? sum1 =65521 :0 ));
printf "%x" $((sum1 65536 * sum2 ))
LC_ALL=""
}
#-- call adler32_awk [text STR] [evaluate text as path bINT]
function adler32_awk ()
{
local -i bPath=$2;
awk -b \
' BEGIN {RS="^$"; bPath='"$bPath"'; for (i=0;i<256;i ) charOrdARR[sprintf("%c",i)]=i; A=1; B=0;}
{
recordSTR=substr($0,1,length($0)-1); if (bPath) {getline byte_data < recordSTR; close(recordSTR);} else byte_data=recordSTR;
l=length(byte_data); for (i=1;i<=l;i ) {
A =charOrdARR[substr(byte_data,i,1)]; if (A>65520) A-=65521;
B =A; if (B>65520) B-=65521;}
printf "%x", lshift(B,16) A; }
' <<<$1
}
time adler32_A "$b"
time adler32_B "$b"
#-- adler 32 of file -> adler32_awk "/home/.../your file" 1
time adler32_awk "$b"