Help with looping in shell scripting

Hi there im totally new to shell scripting and i find it very interesting. I come from java programming background.

Basically what i need is to loop a string of say all possible permutations of 20 displayable characters and md5 hash the string till it produces a 128 bit hash value with say 4 leading hex zeros. (meaning the first 4 characters of the hash value) Is this possible in shell scripting? (bash)

Thanks for the help!!!

My overly simplistic answer would be: yes, anything's possible in shell scripting...

Not to be a wise-guy, but loops are loops...and most languages are simply restacks of others based on the priorities, preferences and motivations of their developers. How would you have done it in your Java background? Start there and we can help you restage it in your new syntax...

After reading some tutorials on shell scripting I got a rough idea...

What I am trying to do is to do a loop on concatStr such that it goes from 0000 to 0001 and 0002 and so forth, each time running thru the md5sum function.

Can anyone help me with the loop syntax?

concatStr="0000"

echo $concatStr | md5sum
for val in $( seq -w 0 9999 )
do
  echo $val | md5sum
done

--ahamed

Thanks for the reply bro,

i did try that... but its not what im looking for. using that, the values are from 0, 1, 2, 3 to 9999 what i need is 0000, 0001, 0002, 0003, to 9999... prefix 0 must be in front in short...

-w in seq serves the purpose of equal width.

root@bt > for val in $( seq -w 0 9999 ); do echo $val ; done | more
0000
0001
0002
0003
0004
0005
0006

--ahamed

Thanks it worked!!! awesome!!!

for i in $( seq -w 0000 9999)
do
  echo $i | md5sum >> /home/ubuntu/Documents/log
done

I got one problem though, when the echo logs into the log file, is there any way to make it stop when one of the md5sum starts with 000000?

example hash value: 000000d414474e4033ac29ccb8653d9b

Try this...

echo $i | md5sum | grep -v ^000000 >> /home/ubuntu/Documents/log

--ahamed

Thanks will try it as soon as i get to a linux terminal... thanks a lot for the assistance!

---------- Post updated at 06:50 PM ---------- Previous update was at 06:34 PM ----------

Hi i tried your grep code, didnt work as planned.

in order to test i wrote this small code....

for i in $(seq -w 100000 100100)
do

echo $i | grep -v ^100088 >> /home/ubuntu/Documents/test_log

done

it didnt stop at 100088 but went all the way to 100100.

Hi.

       -m NUM, --max-count=NUM
              Stop reading a file after NUM matching lines ...

excerpt from man grep, q.v.

for GNU grep 2.5.3

Best wishes ... cheers, drl

The code provided wasn't supposed to stop there... Your request was not to include any hash strings starting with 0000...

--ahamed

Hi.

He asked that question on post # 7:

... cheers, drl

this works for me:

for i in $( seq -w 0000 9999); 
do  
  hash=`echo $i | md5sum`; 
  echo $hash >> /tmp/somefile; 
  if [ `echo $hash|cut -c -4` == '0000' ]; 
  then 
    break; 
  fi;  
done; 

However... it seams there are no hashes that start with four zeros.
You can verify this by changing the condition to:

if [ `echo $hash|cut -c -3` == '000' ];

or even removing the condition and then greping the output file for '^0000' (i.e. lines with four zeros at their beginning.

PS. Note that while this does work, it is not very efficient. As all the piping invokes subshels. 10Kiterations, with quite a few subshells in each iteration.... plenty of room for optimization. :wink:

Thanks for the tip... thats exactly what I am using, it takes very long tho. u only see 0000 - 9999 here because its just for the proof of concept. Really wonder if theres anyway to make it faster by a whole lot...

Correct me if I am wrong. You want to stop the hash when it hits a string starting with 00000? Is it?

--ahamed

What i actually want to accomplish is for eg loop values 0000-9999, hashing each value with md5 and stop when say the hash value (in hex) starts with 0 and tells me which value from 0000-9999 did that hash came from. Does not have to write the hashes into any output log since it really takes a long time.

Something this?

for val in $( seq -w 0000 9999 )
do
  hash=$( echo $val | md5sum )
  [[ $hash =~ "^0000" ]] && echo "$val produced 0000 hash string" || echo $val >> log
done

--ahamed

Hi.

Here is a comparison of the shell script and perl script. Both produce a line at "2345" so that you can see they are working and that the calculations match:

#!/usr/bin/env bash

# @(#) s1	Demonstrate shell vs perl for specific md5 value.

# Utility functions: print-as-echo, print-line-with-visual-space, debug.
# export PATH="/usr/local/bin:/usr/bin:/bin"
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
C=$HOME/bin/context && [ -f $C ] && $C md5sum perl

time {
first=89752
last=89760
pl " Results, $first ... $last, all in shell:"
for val in $( seq -w $first $last )
do
  hash=$( echo $val | md5sum )
  db " hash is $hash"
  [ $val -eq 2345 ] && pe " $val -> $hash, shell md5sum"
  [[ $hash =~ ^0000 ]] &&
  echo "$val produced 0000 hash string: $hash" ||
  echo $val >> log
done
}

time {
first=0000
last=9999
pl " Results, $first ... $last, all in shell:"
for val in $( seq -w $first $last )
do
  hash=$( echo $val | md5sum )
  db " hash is $hash"
  [ $val -eq 2345 ] && pe " $val -> $hash, shell md5sum"
  [[ $hash =~ ^0000 ]] &&
  echo "$val produced 0000 hash string" ||
  echo $val >> log
done
}

time {
first=2345
last=2346
pl " Results, $first ... $last, in perl:"
./p1 $first $last
}
time {
first=0000
last=9999
pl " Results, $first ... $last, in perl:"
./p1 $first $last
}

time {
first=00000
last=99999
pl " Results, $first ... $last, in perl:"
./p1 $first $last
}

exit 0

producing:

% ./s1

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution        : Debian GNU/Linux 5.0.8 (lenny) 
GNU bash 3.2.39
md5sum (GNU coreutils) 6.10
perl 5.10.0

-----
 Results, 89752 ... 89760, all in shell:
89752 produced 0000 hash string: 00009d1a40b9e983bef130790f3101e5  -

real	0m0.051s
user	0m0.008s
sys	0m0.020s

-----
 Results, 0000 ... 9999, all in shell:
 2345 -> c47abe049e90cd2d285fd697ca4a8c6a  -, shell md5sum

real	0m32.657s
user	0m7.616s
sys	0m22.637s

-----
 Results, 2345 ... 2346, in perl:
 2345 -> c47abe049e90cd2d285fd697ca4a8c6a, perl Digest::MD5 (md5_hex)

real	0m0.015s
user	0m0.012s
sys	0m0.000s

-----
 Results, 0000 ... 9999, in perl:
 2345 -> c47abe049e90cd2d285fd697ca4a8c6a, perl Digest::MD5 (md5_hex)

real	0m0.058s
user	0m0.040s
sys	0m0.004s

-----
 Results, 00000 ... 99999, in perl:
 02345 -> 9d129bafb8d74f63aca3d3015269b48c, perl Digest::MD5 (md5_hex)
89752 produces md5 hash of 00009d1a40b9e983bef130790f3101e5

real	0m0.274s
user	0m0.244s
sys	0m0.008s

I am not suggesting that you must do this in perl, but I think you can see that shell is probably not the best choice.

Best wishes ... cheers, drl