ExifTool Forum

ExifTool => Newbies => Topic started by: Tarn on March 19, 2013, 05:12:24 PM

Title: A few questions about operators
Post by: Tarn on March 19, 2013, 05:12:24 PM
Hi Phil,

1.   The command: -if "$ColorSpace =~ /^(sRGB)/" -FileName -ColorSpace . -T works like a charm.
   The command: -if "$ColorSpace = /^(sRGB)/" -FileName -ColorSpace . -T  does not.
   What is the significance of the tildi?

2.   The command: -if "$ColorSpace !~ /^(sRGB)/" -FileName -ColorSpace . -T works like a charm.
   The command: -if "$ColorSpace ne /^(sRGB)/" -FileName -ColorSpace . -T does not.
   Does !~ equal ne? Why does ne not work in this case?

3.   The command: -if "$ColorSpace =~ /^(Adobe|Uncal)/ and $UserComment !~ /^_/" -FileName -Colorspace . works like a charm.
   What does the carrot do? =~ means equal, / is used to enclose the argument, the pipe equals the "OR" statement; but I do not understand what the carrot does.

4.   The command: -if "$ColorSpace ne /(^\s*$)/" -Filename -ColorSpace . does exactly as I want.
   a) Why does ne work in this case, and not in the above example? (!~ works as well)
   b) / /       begins, and ends the argument... got that part.
     ( )       Why are the braces required to enclose the statement (it fails when I remove them)?
     ^       Has something to do with string comparison, but I don't know what it does.
      \       To me, this is part of a path statement. I have no idea what it's function is here.
     s*$   I'm guessing these go together to perform the function that checks for a null value. Right? Wrong?

Sorry if these seem like trite questions. I've visited dozens of sties that tout that they are for "newbies". Unfortunately none of them have the basic, down and dirty explanations of what the different operators do. They show you tons of examples; all using different combinations of operators. Sadly, they leave it up to the noob to figure out what the operators are doing. No one, besides you, ever simply comes out and says "The dollar sign '$' treats the data as a string value." or "ne means not equal for a string function; <> means not equal for a numeric function." and things like that.

Thanks for your time.
Title: Re: A few questions about operators
Post by: Phil Harvey on March 19, 2013, 07:54:01 PM
Hi Tarn,

The answers to 1, 2 and 3 are:  This is a Perl binding operator.  It binds a variable to a regular expression.  "VAR !~ EXPR" is the logical negation of this, and is the same as "not (VAR =~ EXPR)".  Read the Perl documentation about operators and regular expressions if you want to know all of the details.

The answer to 4 is that it should not work.  I don't know why you think it does.

Keep in mind that this is an advanced feature of ExifTool, and can actually be very trick, even for experience programmers.

- Phil
Title: Re: A few questions about operators
Post by: Tarn on March 20, 2013, 04:17:53 AM
Hi Phil,

Quote from: Phil Harvey on March 19, 2013, 07:54:01 PM
Hi Tarn,

The answers to 1, 2 and 3 are:  This is a Perl binding operator.  It binds a variable to a regular expression.  "VAR !~ EXPR" is the logical negation of this, and is the same as "not (VAR =~ EXPR)".  Read the Perl documentation about operators and regular expressions if you want to know all of the details.
Is that the documentation that is in the full version download?

Quote
The answer to 4 is that it should not work.  I don't know why you think it does.
I would take your word for it if it weren't for the fact that it does. Change the "=~" to "ne" and it does the opposite. I've adapted it to do several different chores, and it works wonders.
U:\130214-Negatives>et -if "$Usercomment =~ /(^\s*$)/" -Filename -Usercomment .
======== ./_DSC0001.JPG
File Name                       : _DSC0001.JPG
User Comment                    :
======== ./_DSC0001a.jpg
File Name                       : _DSC0001a.jpg
User Comment                    :
    1 directories scanned
    2 image files read

I got that from StarGeek, see this thread: https://exiftool.org/forum/index.php/topic,4797.0.html

Quote
Keep in mind that this is an advanced feature of ExifTool, and can actually be very trick, even for experience programmers.
I am very well aware that this is an advanced feature. I am just as aware that it is a tricky expression, especially for a noob like me.  And I am very grateful that it works. I'm just trying to learn why it works. And now, I'm even more curious because you say it shouldn't work.
Title: Re: A few questions about operators
Post by: Phil Harvey on March 20, 2013, 07:51:52 AM
Quote from: Tarn on March 20, 2013, 04:17:53 AM
I would take your word for it if it weren't for the fact that it does. Change the "=~" to "ne" and it does the opposite. I've adapted it to do several different chores, and it works wonders.

With "ne", the test will fail for every file (due to a syntax error).  Yes, this is the opposite of "~=" if it passed for every file, but that doesn't mean it is working.  Add the -v option to your command to see any warnings generated by your -if expression.

- Phil
Title: Re: A few questions about operators
Post by: Tarn on March 20, 2013, 04:42:41 PM
I shall do that, thanks.
Title: Re: A few questions about operators
Post by: Tarn on March 20, 2013, 05:12:23 PM
Hi Phil,

First off, let me make sure that you understand that I am NOT disputing you, nor am I contesting you in any way. You say this should fail, I believe you. I take your word as gospel. I am simply trying to understand why it seems to be working. Is it something I'm doing wrong? Something about my system? Or something else.

With that, attached is a the batch file, and the output of that file. I'd like to ask you to look at them and see if you can pin point what I'm doing wrong. I'm working with only two files; b.jpg and c.jpg. b.jpg has data in UserComment, c.jpg does not.

P.S. While we are at it, what would be the correct way to check a tag for a null value?

Thanks
Title: Re: A few questions about operators
Post by: Phil Harvey on March 20, 2013, 07:38:06 PM
Hi Tarn,

You don't need to worry about hurting my feelings.  I really enjoy being proven wrong.

Now you have supplied enough information for me to reproduce this effect.  Very interesting.

I see what is happening, but is is deeply nefarious.

1) Since you haven't bound your regular expression to a variable with "=~", it operates on the default input variable.

2) It just so happens that the default input variable contains the file name specified on the command line at this point in the code, "." for this command.

3) The regular expression returns true (1) if the pattern matches the default input variable variable, and false (an empty string) otherwise.

4) The condition fails for c.jpg because it contains no UserComment.

5) The condition passes for b.jpg because the regular expression returns an empty string, and this is not equal to the UserComment.

So it wasn't testing the UserComment with your expression, it was just comparing your UserComment to the empty string, which just happened to give the result you expected.

But now I don't understand something.  Why does this pass the condition for c.jpg?:

U:\images>et -if "$Usercomment =~ /(^\s*$)/" -Filename -Usercomment . -f
======== ./c.jpg
File Name                       : c.jpg
Usercomment                     : -
    1 directories scanned
    1 files failed condition
    1 image files read


I get a different result:

> exiftool -filename -usercomment -f .
======== ./a.jpg
File Name                       : a.jpg
User Comment                    : a.jpg
======== ./b.jpg
File Name                       : b.jpg
Usercomment                     : -
    1 directories scanned
    2 image files read

> exiftool -if '$Usercomment =~ /(^\s*$)/' -filename -usercomment -f .
    1 directories scanned
    2 files failed condition
    0 image files read


Note that I use single quotes because I am on a Mac. 

I can't explain why the above command reads 1 of your files.

- Phil
Title: Re: A few questions about operators
Post by: Tarn on March 21, 2013, 07:28:08 AM
Hi Phil,

I'm not sure what you mean by I haven't bound my regular expresion to a variable; isn't that what the "=~" between "$Usercomment" and "/^(\s*$)/" is doing?

Anyway, I tried changing the "." to a "*" just to see what happenes. The results are below.
The dir is so you can see what files are there.


U:\images>dir /o
Volume in drive U is Terrabak
Volume Serial Number is 44E2-27C3

Directory of U:\images

03/21/2013  01:27 AM    <DIR>          .
03/21/2013  01:27 AM    <DIR>          ..
03/21/2013  04:01 AM    <DIR>          temp
03/21/2013  01:27 AM            51,843 b.jpg
03/21/2013  01:27 AM            45,509 c.jpg
03/18/2013  10:34 PM            92,209 image.jpg
               3 File(s)        189,561 bytes
               3 Dir(s)  523,606,736,896 bytes free

U:\images>et -if "$Usercomment =~ /(^\s*$)/" -Filename -Usercomment . -f
======== ./c.jpg
File Name                       : c.jpg
Usercomment                     : -
======== ./image.jpg
File Name                       : image.jpg
Usercomment                     : -
    1 directories scanned
    1 files failed condition
    2 image files read

U:\images>et -if "$Usercomment =~ /(^\s*$)/" -Filename -Usercomment * -f
======== c.jpg
File Name                       : c.jpg
Usercomment                     : -
======== image.jpg
File Name                       : image.jpg
Usercomment                     : -
======== temp/c-temp.jpg
File Name                       : c-temp.jpg
Usercomment                     : -
======== Thumbs.db
File Name                       : Thumbs.db
Usercomment                     : -
    1 directories scanned
    2 files failed condition
    4 image files read

U:\images>


I hope this sheds some light on the subject for you. As for me, I'm still in the dark.

Title: Re: A few questions about operators
Post by: Phil Harvey on March 21, 2013, 07:57:20 AM
Hi Tarn,

Quote from: Tarn on March 21, 2013, 07:28:08 AM
I'm not sure what you mean by I haven't bound my regular expresion to a variable; isn't that what the "=~" between "$Usercomment" and "/^(\s*$)/" is doing?

I'll answer this by quoting myself:

Quote from: Phil Harvey on March 19, 2013, 07:54:01 PM
The answers to 1, 2 and 3 are:  This is a Perl binding operator.  It binds a variable to a regular expression.

...maybe this comment makes a bit more sense now. :)

- Phil