views:

47

answers:

3

I am making a bash script where I want to find files that are equal to a variable. The equals will then be used.

I want to use "mogrify" to shrink a couple of image files that have the same name as the ones i gather from a list (similar to "dpkg -l"). It is not "dpkg -l" I am using but it is similar. My problem is that it prints all the files not just the equals. I am pretty sure this could be done with awk instead of a for-loop but I do not know how.

prog="`dpkg -l | awk '{print $1}'`"

for file in $dirone* $dirtwo*
do
     if [ "basename ${file}" = "${prog}" ]; then
         echo ${file} are equal
     else
         echo ${file} are not equal
     fi
done

Could you please help me get this working?

+1  A: 

The condition "$file = $prog" is a single string. You should try "$file" = "$prog" instead.

The following transcript shows the fix:

pax> ls -1 qq*
qq
qq.c
qq.cpp

pax> export xx=qq.cpp

pax> for file in qq* ; do
         if [[ "${file} = ${xx}" ]] ; then
             echo .....${file} equal
         else
             echo .....${file} not equal
         fi
     done
.....qq equal
.....qq.c equal
.....qq.cpp equal

pax> for file in qq* ; do
         if [[ "${file}" = "${xx}" ]] ; then
             echo .....${file} equal
         else
             echo .....${file} not equal
         fi
     done
.....qq not equal
.....qq.c not equal
.....qq.cpp equal

You can see in the last bit of output that only qq.cpp is shown as equal since it's the only one that matches ${xx}.

The reason you're getting true is because that's what non-empty strings will give you:

pax> if [[ "" ]] ; then
         echo .....equal
     fi

pax> if [[ "x" ]] ; then
         echo .....equal
     fi
.....equal

That's because that form is the string length checking variation. From the bash manpage under CONDITIONAL EXPRESSIONS:

string
-n string
          True if the length of string is non-zero.


Update:

The new code in your question won't quite work as expected. You need:

if [[ "$(basename ${file})" = "${prog}" ]]; then

to actually execute basename and use its output as the first part of the equality check.

paxdiablo
Thanks but i am not using #C just bash and that is a bit over my comprehension. I tried using "$file" = "$prog" instead but it will just give me "no files where equal". I just realise that $file will give me both path and program name but the $prog will only give me the name of the program.
AlMehdi
@AlMehdi, there's no C/C++/C# there, that just happens to be the files in that directory that I used for testing. The solution is pure `bash`. The problem you had was that the equality statement was actually a string-size statement. Your _new_ problem can be fixed with `basename`, which will give you the file part of a full file spec.
paxdiablo
I see.. looked a lot more complicated. I was fooled by the ".c" and ".cpp". But i see now and i have tried it. Now i have "if [ "basename ${file} = ${prog}" ];". But it still don't give me equals.
AlMehdi
ahh.. it might be $prog that is wrong. It puts the program names after each other separated with a space. i.e. "gimp deluge xournal".
AlMehdi
A: 

you can use case/esac

case "$file" in
  "$prog" ) echo "same";;
esac
ghostdog74
Thanks for the answer.. didn't try it. I am sure it is good but I got it working with the for-loop.
AlMehdi
A: 

First, I think there's a small typo. if [ "basename ${file}" =... should have backticks inside the double quotes, just like the prog=... line at the top does.

Second, if $prog is a multi-line string (like dpkg -l) you can't really compare a filename to the entire list. Instead you have to compare one item at a time to the filename.

Here's an example using dpkg and /usr/bin

#!/bin/bash
progs="`dpkg -l | awk '{print $2}'`"

for file in /usr/bin/*
do
    base=`basename ${file}`

    for prog in ${progs}
    do
        if [ "${base}" = "${prog}" ]; then
            echo "${file}" matches "${prog}"
        fi
    done
done
Martin
Thanks! This is exactly what i am after.. but i didn't get it to work. I am checking if i misspelled something.
AlMehdi
Usual caveats apply re spaces in filenames but, other than that, this looks good.
paxdiablo
I got it! the basename did show the ".png" which the "dpkg -l" didn't have. So when i added that it works!Thanks a lot ;)
AlMehdi