views:

374

answers:

6

My bash script doesn't work the way I want it to:

#!/bin/bash

total="0"
count="0"
#FILE="$1" This is the easier way
for FILE in $*
do
    # Start processing all processable files
    while read line
    do
        if [[ "$line" =~ ^Total ]];
        then
            tmp=$(echo $line | cut -d':' -f2)
            count=$(expr $count + 1)
            total=$(expr $total + $tmp)
        fi     
    done < $FILE
done
echo "The Total Is: $total"
echo "$FILE"

Is there another way to modify this script so that it reads arguments into $1 instead of $FILE? I've tried using a while loop:

while [ $1 != "" ]
  do ....
done

Also when I implement that the code repeats itself. Is there a way to fix that as well?

Another problem that I'm having is that when I have multiple files hi*.txt it gives me duplicates. Why? I have files like hi1.txt hi1.txt~ but the tilde file is of 0 bytes, so my script shouldn't be finding anything.

A: 

Hi again,

Another problem that im having is that when i have multiple files hi*.txt it will give me duplicates..why?? I do have files like hi1.txt hi1.txt~ but the tilde file is of 0 bytes..so my script shouldnt be finding anything.

I moved the content of this answer to the bottom of the question. @lampshade: please delete this answer. @others: please don't downvote it until removed.
Federico Ramponi
+1  A: 

If you define a function, it'll receive the argument as $1. Why is $1 more valuable to you than $FILE, though?

#!/bin/sh

process() {
    echo "doing something with $1"
}

for i in "$@" # Note use of "$@" to not break on filenames with whitespace
do
    process "$i"
done
Dustin
+1  A: 
while [ "$1" != "" ]; do
    # Code here

    # Next argument
    shift
done

On your problem with tilde files ... those are temporary files created by your text editor. Delete them if you don't want them to be matched by your glob expression (wildcard). Otherwise, filter them in your script (not recommended).

strager
A: 

Thats cool i didnt know that. I had no idea that they were treated as $1. but thats making it to complicated...What i mean is the for loop:

for FILE in $1 <-- will receive only 1 arg.. for FILE in $2 <-- will receive only 1 arg but as the second item..

like hi[12].txt hi2.txt will only be read..

You must format things correctly for things to be read. $1 is the first argument of your script or function. If this isn't the behavior you want, don't use $1 or $2.
Dustin
Use either the shift operator (see my answer) or the $@ or $* variables (see Dunstin's answer).
strager
+2  A: 

It looks like you are trying to add up the totals from the lines labelled 'Total:' in the files provided. It is always a good idea to state what you're trying to do - as well as how you're trying to do it (see How to Ask Questions the Smart Way).

If so, then you're doing in about as complicated a way as I can see. What was wrong with:

grep '^Total:' "$@" |
cut -d: -f2 |
awk '{sum += $1}
     END { print sum }'

This doesn't print out "The total is" etc; and it is not clear why you echo $FILE at the end of your version.

You can use Perl or any other suitable program in place of awk; you could do the whole job in Perl or Python - indeed, the cut work could be done by awk:

grep "^Total:" "$@" |
awk -F: '{sum += $2}
         END { print sum }'

Taken still further, the whole job could be done by awk:

awk -F: '$1 ~ /^Total/ { sum += $2 }
         END { print sum }' "$@"

The code in Perl wouldn't be much harder and the result might be quicker:

perl -na -F: -e '$sum += $F[1] if m/^Total:/; END { print $sum; }' "$@"

When iterating over the file name arguments provided in a shell script, you should use '"$@"' in place of '$*' as the latter notation does not preserve spaces in file names.

Your comment about '$1' is confusing to me. You could be asking to read from the file whose name is in $1 on each iteration; that is done using:

while [ $# -gt 0 ]
do
     ...process $1...
     shift
done

HTH!

Jonathan Leffler
A: 

What i have is fine, but could be improved. I appreciate your awk suggestions but its currently beyond my level as a unix programmer.

Strager: The files that my text editor generates automatically contain nothing..it is of 0 bytes..But yeah i went ahead and deleted them just to be sure. But no my script is in fact reading everything twice. I suppose its looping again when it really shouldnt. I've tried to silence that action with the exit commands..But wasnt successful.

while [ "$1" != "" ]; do
    # Code here

    # Next argument
    shift
done

This code is pretty sweet, but I'm specifying all the possible commands at one time. Example: hi[145].txt If supplied would read all three files at once. Suppose the user enters hi*.txt; I then get all my hi files read twice and then added again.

How can I code it so that it reads my files (just once) upon specification of hi*.txt? I really think that this is because of not having $1.

I'm not really sure why your code would process twice. Try echo'ing your $1 to see what files are being processed.
strager
Remember, StackOverflow identifies code by four-space indentation of blocks, not a [code] tag. Also, please edit your original post instead of "answering" your question. This separates answers from questions and keeps things better organized.
strager