PDA

View Full Version : Bash programming looping over input files



tejas.deshpande
December 23rd, 2010, 03:55 PM
Hi,
I'm an absolute noob on bash programming and I wanted to do the following.

I write a solution for a programming contest problem. I have a few test cases (10 to be precise) named 1.in , 2.in , 3.in and so on and I have the correct outputs names 1.out, 2.out....

So what I want to be able to do is run my c++ program with sequential inputs from 1.in , 2.in etc and test the output given by my program with 1.in and compare it with 1.out (I figured I would have to use the 'diff' program).

I have written the code
for i in 'seq 1 10'; do ./The\ Siruseri\ Sports\ Stadium < $j.in > my$j.out; done

but its giving .in is not a valid file name.


Also, I would also like to see for how much time program ran.

Thanks! :)

thk
December 23rd, 2010, 08:48 PM
You probably already found the typo, but notice that you loop over i and then use j in the "do" section. Also, you must use backticks around 'seq'. It should be something like


for i in `seq 1 10`
do
./The\ Siruseri\ Sports\ Stadium < ${i}.in > my${i}.out
done

Crusty Old Fart
December 25th, 2010, 07:54 PM
...Also, I would also like to see for how much time program ran.

Thanks! :)
Here it is with the execution time duration you asked for, and my personal preference of a slightly different coding style:


!/bin/bash
set -e

start=$(date +%s.%N)

for i in $(seq 1 3); do
./The\ Siruseri\ Sports\ Stadium < $i.in > my$i.out
done

end=$(date +%s.%N)
duration=$(echo "$end - $start" | bc -l)
echo -e "\nScript execution time:" $(printf "%1.9f" $duration) "seconds.\n"

exit 0

AlexC_
December 26th, 2010, 12:34 PM
Also, you must use backticks around 'seq'. It should be something like

The use of backticks should only be used when you're wanting compatibility with other (or older) shells. You pretty much always want to use $() over ``. Also, no need to use 'seq' when using Bash ...


#!/bin/bash
for i in {1..3}; do
./The\ Siruseri\ Sports\ Stadium < $i.in > my$i.out
done
exit 0


Here it is with the execution time duration you asked for, and my personal preference of a slightly different coding style:


!/bin/bash
set -e

start=$(date +%s.%N)

for i in $(seq 1 3); do
./The\ Siruseri\ Sports\ Stadium < $i.in > my$i.out
done

end=$(date +%s.%N)
duration=$(echo "$end - $start" | bc -l)
echo -e "\nScript execution time:" $(printf "%1.9f" $duration) "seconds.\n"

exit 0


Why use all that when 'time' exists?


time ./foo

Crusty Old Fart
December 26th, 2010, 06:21 PM
Note to tejas: I reduced the count limit in your for statement to make only three loops so my code testing would be easier. I forgot to change it back to 10 when I posted. Sorry about that.


The use of backticks should only be used when you're wanting compatibility with other (or older) shells. You pretty much always want to use $() over ``...
Yup...That and it's a helluva lot easier for old eyes to read. I was so glad when I learned that those itty-bitty backticks could be replaced with: $(), especially when backticks are adjacent to single quotation marks.



Also, no need to use 'seq' when using Bash ...

#!/bin/bash
for i in {1..3}; do
./The\ Siruseri\ Sports\ Stadium < $i.in > my$i.out
done
exit 0
Oooh...Thank you, AlexC. I didn't know about that one. I LIKE it.



Why use all that when 'time' exists?


time ./foo
Two reasons:


The code I wrote is internal to the script.
It not only provides more precision (all the way down to nanoseconds) but is more accurate as well. (See "man time" for accuracy issues.)

I reckon "foo" could be just like you have it in your code box, and then if custom formatting for the output from the "time" command was desired, a bash wrapper (e.g.: "foobar") could look something like this:


#!/bin/bash
/usr/bin/time -f "Script execution time: %e seconds." ./foo
exit 0
and then...running "bash foobar" would give output similar to this:
Script execution time: 3.07 seconds.

But all this gymnastics, kind of defeats the quest for code brevity, which seems to be your intention by suggesting the "time" command.

Ultimately, it all comes down to what the customer wants. In this case, tejas was a little short on specifics. If he reads our posts, he'll have a few more choices, eh?

Thank you again for popping in here. You gave me a few things to add to my bag of tricks.

Crusty