Do something only that last iteration of loop

I have a script with logic like:


my_function()
{
if [ $2 ]
mkdir $1
mkdir mydir_${2}
else
do something else
fi
}

read in list of items
while read list 
do
my_function $list `date`
done

so basically it will make a directory for every name in the list and create a directory with the date appended (which I only want to do once). What I want to know is how do I perform the line "mkdir mydir_${2}" only once? This is not the script itself, so this example it a bit silly, but the logic is there, I want to iterate through a list and call a function with each item in the list, but there is one element in the function that should only happen once.. Assume that the argument $2 is something that will not change through each iteration, so I do not want to repeat the process doing the same thing over and over. Is there a better solution than to create another function and call it? There is a reason that I dont move this line out of the function, but it's difficult to explain without posting my company's intellectual property.

If it's something you only do once, it t really belong in a function you call 10,000 times. Do it before the loop.

This is especially true since the value of `date` may change if your script takes a long time to finish! Even if it doesn't, you're running date 10,000 times when all you needed was to run it once. Save it into a variable.

What is this if [ $2 ] ? I suspect that doesn't do what you think it does.

DATE=`date`

function() {
        echo asdf
}

mkdir mydir_${DATE}

while ...
do
        function ...
done

if [ $2 ] I am using this to mean test if $2 has a value

Use -z for that. -z tests if a string is blank.

if [ ! -z "$2" ]
then
        echo "value $2"
else
        echo "2 is blank"
fi

And don't leave out the quotes. [ ! -z ] is a syntax error, [ ! -z "" ] is not.

1 Like

Such badness can be done.

DATE=`date`
# global variable stores a state of a function
gdone=0

func() {
        echo asdf
 if [ $gdone -eq 0 ]
 then
  gdone=1
  mkdir mydir_${DATE}
 fi
}

while ...
do
        func
done
1 Like

There's lots of ways to do it.

You could mkdir -p, so mkdir won't complain when the directory already exists.

You could [ -d dirname ] || mkdir dirname.

You could mkdir dirname 2>/dev/null and just ignore all errors.

The problem is, you're either doing or checking something 10,000 times, that you didn't need to do even once, adding three lines of code to your function to save one line of code outside it. Why bother?

I apologize, this was a poor question. I should just move the line out of the loop, there is no better solution. Thank you for all of your help.