display echo only once

lets say I am printing something out

echo "Please enter a valid username"

and its being printed out 5 times, is there any way I can limit to only being displayed ONCE. I tried echo -n but that just makes everything fit on one line.

Right now it keeps saying

Please enter a valid username
Please enter a valid username
Please enter a valid username
Please enter a valid username
Please enter a valid username
Please enter a valid username
Please enter a valid username

and I want it displayed only once

thanks

Do you have it in a loop? Sounds to me like something other than the echo is your problem.

It would be helpful to see your script along with the shell that you are using and O/S.

sure thing it is a for loop

#!/bin/bash

for img in *.jpg
do
        if [ $# -gt 0 ]
then
        jpegtopnm "$img" | pnmscale -height 200 | pnmtojpeg > "${img%.jpg}-thumb.jpg"
        echo $img
else
        echo -n  "Please provide a proper image file"
fi
shift
done

what its doing is taking any file ending in .jpg in the current directory and making it into a thumbnail. I am running into a problem where I want it to display the error message only if no arguments are provided on the command line. I am not doing it right :wall:

Its my fault for trying to make it convert everything in the directory ending in .jpg using the FOR loop but I'm at the same time trying to feed an argument on the command line . . I am in a pickle... I would much rather just feed it command line but at the same time have it being able to take 1 argument or even a list but still give an error if no arguments are being displayed. Im new to this sorry. Any help is appreciated.

bad post

First off, there seems to be some confusion in your code:

for img in *.jpg
do
        if [ $# -gt 0 ]
            ....

        shift
done

What is the for loop supposed to cycle through? The arguments given or the files with a certain ending?

Apart from that, one of the three utilities in this pipeline:

jpegtopnm "$img" | pnmscale -height 200 | pnmtojpeg > "${img%.jpg}-thumb.jpg"

now print an error message every time some error condition occurs. As the condition occurs repeatedly the message is printed several times.

If you want to print it only once use a flag (which you raise when the condition occurs) and only at the end print the message depending on the status of the flag. The usual way to do this is to redirect error messages to "/dev/null" and use the exit code of the program(s) as indication if everything has gone ok.

So, your code should look something like this:

#!/bin/bash

local lErrorFlag=0

for img in *.jpg
do
        if [ $# -gt 0 ]
then
        jpegtopnm "$img" | pnmscale -height 200 | pnmtojpeg > "${img%.jpg}-thumb.jpg" 1>/dev/null 2>/dev/null
        if [ $? -gt 0 ] ; then
             lErrorFlag=1
        fi
        echo $img
else
        echo -n  "Please provide a proper image file"
fi
shift
done

if [ $lErrorFlag -gt 0 ] ; then
     echo "<your error message here>"
fi

But there is still some gotcha: in pipelines only one return code is given back and it not completely standardized which one this is. Depending on which OS and shell you use and which options you use (see for instance "set -o pipefail" in bash) you might get differing results.

I hope this helps.

bakunin

You have a couple of options. Test before entering the for loop and exit immediately after writing the error message:

if (( $# < 1 ))
then
   echo "you must enter a name to convert"
   exit
fi

ls *.jpg | while read img
do
    jpegtopnm "$img" | pnmscale -height 200 | pnmtojpeg > "${1%.jpg}-thumb.jpg"
done

However, since you are not using the information on the command line it seems odd that you would require it be entered. Maybe you are intending to get parameters or something from the command line; if that is the case then this would allow for you to validate and continue if you get the information.

However, the message in your code implies that you want the user to enter an image file to convert. If they enter a file, do you want to just convert the ones on the command line, but default to converting everything if they don't enter any filename? If so, you could do something like this:

function mk_thumb
{
    # probably wise to add code to verify that $1 is an image file, exists etc.
    jpegtopnm "$img" | pnmscale -height 200 | pnmtojpeg > "${1%.jpg}-thumb.jpg"
}

if (( $# > 0 ))             # if command line parms, process just them
then
    while [[ -n $1 ]]
    do
        mk_thumb $1
        shift
    done
else                        # no parms, then convert all
    ls *.jpg | while read img
    do
        mk_thumb $img
    done
fi

This invokes the conversion function once for each command line parm (the function probably should verify that it exists and is a proper file type etc.). If no parameters are entered, then it invokes the function for all jpg files in the current directory.

I've not really tested either of these, but you should get an idea of your options.