LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Need help with array of images in Bash (https://www.linuxquestions.org/questions/programming-9/need-help-with-array-of-images-in-bash-815690/)

alos31 06-22-2010 10:46 AM

Need help with array of images in Bash
 
Hi I am a newbe to bash programming and need some help. I am building a pipeline for image processing. I would like to be able to take the png images in a folder and pass them to clusterImage.pl once that is done I would like to then pass the outputted file to seperateObjects.pl the outputted file is of the same name but has kmeansOutput.all.matrix attached to the end. Below is what I have so far, but it is not working.
Any help would be greatly appreciated. Thank you

#!/bin/bash
#This script will take in an image and a matrix file.
#The output will be an image and a matrix file.

list=`ls *.png`
for i in $list
do
$file="./$list"
$image_array = $list
echo $file
#Cheching to see if the file exists.
for((j=0;j<=i;j++))
do
if [ -e image_array[j] ]; then
echo $file
echo "Begining processing"
#Take in an image and create a matrix from it.
perl clusterImage.pl SampleImage.png
#Take in a matrix and draw a picture showing the centers of all
#of the colonies.
perl seperateObjects.pl SampleImage.png.kmeansOutput.all.matrix
echo "Ending processing"
else
echo "There is an issue"
fi
done
done

penguiniator 06-22-2010 02:02 PM

Code:

list=`ls *.png`
for i in $list
do
$file="./$list"

There are a couple of problems in just your first few lines of code. First, you are trying to create a list, which itself is not a problem. But your syntax will not result in a list of png files as you expect. The Arrays section of the bash manual shows how to create lists.

The way you are trying to operate on the values stored in the list in your for loop is also flawed. A list variable's values may be accessed using subscripts. Two particular subscripts will let you iterate over all the items in a list: * and @. The same section of the bash manual will explain this.

The next problem is related to the second one. You appear to by attempting to assign a single item of your list to the variable file, but without using a subscript and treating it as a single filename. This simply will not work as you expect. Also, the assignment statement itself is flawed, because you use a $ to refer to the variable file. The dollar sign is only used with a variable name when you want access to the value stored in the variable, not when you are manipulating the variable itself.

If I understand your logic correctly, you want to create a list of existing png files in the current directory. Then, with each file in the list you want to echo the filename and process it with two Perl scripts. I'm not familiar with the Perl script you refer to in your code. But there appears to be a problem with your logic. You have a second for loop nested inside the first one which refers to the i variable of the outer loop. You treat i as a number, but it will be a string (once you fix your list creation code). Therefore, the code: j<=i will be an ambiguous comparison at best.

The test in your if statement does not dereference the item in your image_array variable correctly. The bash manual section about arrays should clear this up.

I'm not sure why you are trying to create multiple copies of your list. You should be able to do all of the work with your list variable. It looks to me like you may be confusing some of Perl's syntax with Bash's. Perl scalar variables are always referenced with: $var. Bash variables are only referenced that way when getting the data stored in them. Otherwise the $ is left off.

David the H. 06-22-2010 02:03 PM

Hmm. Kind of confused here. Almost too many issues to mention.

First of all, please use [code][/code] tags, to preserve the formatting of the code. It's hard to follow the script without indenting. I had to copy it to a file and re-format it to figure it out.

Now, from the top

Code:

list=`ls *.png`  #not so good
1. $(..) is recommended over `..`
2. You shouldn't need to use ls to create a list of files. Bash has it's own globbing ability.

Code:

$file="./$list"  #wrong
I'm not sure what you're trying to do here. This just appends ./ to the front of the first entry in the list of files you created earlier. Not to mention that you never, ever use $ when setting a variable.

Code:

$image_array = $list  #wrong!
Is this supposed to be the place where you populate the array? Because this is exactly NOT how to do that in bash.

Code:

for((j=0;j<=i;j++))  # not ok
(edit: I just noticed that this is wrong too, since $i is not an integer)

Anyway, there's a more convenient way to loop through array elements in bash.

Code:

for j in ${!image_array[@]} ; do  #better
${!array[@]} outputs a list of all existing array indexes.

Code:

if [ -e image_array[j] ]; then  #wrong
You do however use $ when you need to fetch the value of a variable (or array element). Also you should generally quote them in order to protect any spaces in the strings from word breaking.

Code:

if [ -e "${image_array[$j]}" ]; then  #right
But why do you need to check if the file exists, when you got the filename from ls in the first place?

Code:

perl clusterImage.pl SampleImage.png
Neither of your perl commands has any input from the array list. I suppose that may be because you're just in testing though.

Anyway, assuming I understand your needs, here's a basic framework of what you should be doing. To tell the truth, I don't see any need at all for an array here, so first of all, here's just a simple loop.

Code:

for i in ./*.png; do

    echo "$i"
    perl clusterImage.pl "$i"  #$i is the input file
    perl seperateObjects.pl "$i.kmeansOutput.all.matrix"  # the input is $i with the string attached

done

This is assuming that the first script modifies the output filename itself and places it in the working directory.

But if for some reason you really need to use an array, then you just make a simple modification to populate and loop through the array. Probably something like this:

Code:

image_array=( *.png )

for i in ${image_array[@]}; do

    echo "$i"
    perl clusterImage.pl "$i"  #$i is the input file
    perl seperateObjects.pl "$i.kmeansOutput.all.matrix"  # the input is $i with the string attached

done

...although details like the exact filename format and the perl command input might be important.

penguiniator 06-22-2010 02:14 PM

The only problem with the corrected logic about existing files is that when you don't use ls to create your list and you use a globbing pattern, if the pattern does not match any files, the pattern itself will populate the list. This will make checking for filename existence necessary.

konsolebox 06-23-2010 01:24 AM

Quote:

Originally Posted by penguiniator (Post 4011767)
... if the pattern does not match any files, the pattern itself will populate the list. This will make checking for filename existence necessary.

Try 'shopt -s nullglob'. Run 'help shopt' for more info.

David the H. 06-23-2010 07:35 AM

Yep, and there's also a "failglob" option, if you'd prefer to have it spit out an error message instead.

alos31 06-23-2010 09:16 AM

Thank you everyone!

penguiniator 06-23-2010 11:04 AM

Didn't know about nullglob. That will come in handy.


All times are GMT -5. The time now is 10:50 AM.