using PERL to search and sort multiple fields

Started by flieckster, January 22, 2020, 10:15:04 PM

Previous topic - Next topic

flieckster

hi there, i'm using exiftool and perl to discover files, then look in the 'Instructions' field for data, if its blank i move it to the next location. i'd like to expand that code to look in 2 fields. once i get my filelist i'm looking at each file with 'foreach' and looking at the tag, whats the best method to add 2 fields to look at? i tired my @tags = qw(Instructions, SpecialInstruction); but foreach seems to look fir the first field, and then move on, then when the next image comes up, it looks in 'specialinstruction' so its only works on every other image.


foreach $file (@fileslist) {
my @tags = qw(Instructions);
$exifTool->Options(Duplicates => 0);
my $tag_find = $exifTool->ImageInfo($file, \@tags);
foreach (@tags) {
if ("$tag_find->{$_}" eq "")
{
print "$file in $row needs to go to $daysumanfolder\n";
print FILE"$date\t$time\t$row\t$day\t$file\t$daysumanfolder\n";

$exifTool->SetNewValue(Instructions => "outsourced $date $time");
$exifTool->SetNewValue(Source => "day$day");
$exifTool->SetNewValue(Label => "Second");
$exifTool->WriteInfo( $file) or warn "$!";
print "this is what daysumanfolder is doing $file $daysumanfolder\n";
copy ($file, $forsumanbasefolder) or warn "copy of bad files failed $!";


greybeard

#1
my @tags = qw(Instructions SpecialInstruction);

Assuming the rest of the code works.

Although I would think
if (!($tag_find->{$_}))
would be better than
if ("$tag_find->{$_}" eq "")

flieckster

this still seems to get every other image as it checks the list of files, seems like having 2 fields doesn't work?


DB-105000320_Black_FT.psd instructions field has data
DB-105000320_DazzlingBlue_BK.psd in /Volumes/photorepos/Partners/Dress_Barn_Online/Post/instock/6 needs to go to /Volumes/photorepos/Partners/OutSource/Outbound/
this is what daysumanfolder is doing DB-105000320_DazzlingBlue_BK.psd /Volumes/photorepos/Partners/OutSource/Outbound/
DB-105000320_DazzlingBlue_BK.psd instructions field has data
DB-105000320_DazzlingBlue_DT.psd in /Volumes/photorepos/Partners/Dress_Barn_Online/Post/instock/6 needs to go to /Volumes/photorepos/Partners/OutSource/Outbound/
this is what daysumanfolder is doing DB-105000320_DazzlingBlue_DT.psd /Volumes/photorepos/Partners/OutSource/Outbound/
DB-105000320_DazzlingBlue_DT.psd instructions field has data
DB-105000320_DazzlingBlue_FT.psd in /Volumes/photorepos/Partners/Dress_Barn_Online/Post/instock/6 needs to go to /Volumes/photorepos/Partners/OutSource/Outbound/
this is what daysumanfolder is doing DB-105000320_DazzlingBlue_FT.psd /Volumes/photorepos/Partners/OutSource/Outbound/
DB-105000320_DazzlingBlue_FT.psd instructions field has data
DB-105000320_ShyBlush_BK.psd in /Volumes/photorepos/Partners/Dress_Barn_Online/Post/instock/6 needs to go to /Volumes/photorepos/Partners/OutSource/Outbound/
this is what daysumanfolder is doing DB-105000320_ShyBlush_BK.psd /Volumes/photorepos/Partners/OutSource/Outbound/
DB-105000320_ShyBlush_BK.psd instructions field has data
DB-105000320_ShyBlush_DT.psd in /Volumes/photorepos/Partners/Dress_Barn_Online/Post/instock/6 needs to go to /Volumes/photorepos/Partners/OutSource/Outbound/
this is what daysumanfolder is doing DB-105000320_ShyBlush_DT.psd /Volumes/photorepos/Partners/OutSource/Outbound/

greybeard

Should it be SpecialInstructions rather than SpecialInstruction?

This sample code should check all the psd files in the current directory and displays which of the two tags has content:

#!/usr/bin/perl

use strict;
use warnings;
use Image::ExifTool;

my @image_files=`ls -1 *.psd`;
foreach my $file (@image_files) {
  chomp($file);
  my $exifTool = new Image::ExifTool;
  $exifTool->Options(Duplicates => 0);
  my @tags = qw(Instructions SpecialInstructions);
  my $hash_ref = $exifTool->ImageInfo($file, \@tags);
  foreach my $tag (@tags) {
    if (!(my $tag_contents = $hash_ref->{$tag})) {
       printf("%-10s %-10s missing\n",$file,$tag);
    } else {
       printf("%-10s %-10s exists %-10s\n",$file,$tag,$tag_contents);
    }
  }
  print "\n";
}

flieckster

this could be part of it, when i run commands to write data into a file, it doens't seem to work?

exiftool -overwrite_original_in_place -R -Instructions=TechCloud  -SpecialInstructions=TechCloud

exiftool -Instructions -SpecialInstructions /Users/flieckb/Desktop/DB-105000318_Blue_FT.psd
Instructions                    :
Special Instructions            : TechCloud


but if i open the file in PS, i can see data in that instructions field?


here is the file in question also. https://we.tl/t-xZ3ag1SrkJ



StarGeek

You need to add the -a (duplicates) option to see all the tags

C:\>exiftool -g1 -a -s -Instructions -SpecialInstructions  Y:\!temp\NewDirectory\DB-105000318_Blue_FT.psd
---- IPTC ----
SpecialInstructions             : TechCloud
---- XMP-photoshop ----
Instructions                    : TechCloud
Instructions                    :


For whatever reason, your file has the Instructions tag twice.

And what I said previously about Bridge also applies to PS.

Quote from: StarGeek on December 18, 2019, 08:45:40 PMBridge will fill the "Instructions" field from either of these tags, depending upon which ones exist.

* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

greybeard

In my sample script you would need to remove the "$exifTool->Options(Duplicates => 0);" line and then you would see:

DB-105000318_Blue_FT.psd Instructions (1) exists TechCloud
DB-105000318_Blue_FT.psd Instructions missing
DB-105000318_Blue_FT.psd SpecialInstructions exists TechCloud

Then, of course, you need to decide what logic you want to follow for the psd file with duplicate tags.

It seems there is a problem in the way the tags are added as there are other duplicate tags in your sample psd file.

flieckster

thanks everyone, is there a best way to remove the extra tags? i'm guessing this was a source of the issue.

greybeard

This should remove any blank Instructions tags from psd files and leave non-blank tags.

Don't understand why it needs the exifversion => "dummy"

#!/usr/bin/perl

use strict;
use warnings;
use Image::ExifTool;

my @tags = qw(Instructions);
my @image_files=`ls -1 *.psd`;
foreach my $file (@image_files) {
  chomp($file);
  my $exifTool = new Image::ExifTool;
  my $hash_ref = $exifTool->ImageInfo($file, \@tags);
  foreach my $tag (sort keys % {$hash_ref}) {
     my $val = $$hash_ref{$tag};
     if ($val eq "") {
        printf("%-50s %-10s blank tag removed\n",$file,$tag);
        $exifTool->SetNewValue($tag => "", DelValue => 1);
        $exifTool->SetNewValue(exifversion => "dummy", DelValue => 1);
     }
  }
  $exifTool->WriteInfo($file);
}

Phil Harvey

To delete a tag, you should do this:

        $exifTool->SetNewValue($tag);

DelValue is used to define an old value for a conditional replacement.  Since you already know the tag is blank, it isn't necessary to have a second condition, and you should just be doing a simple deletion.

But I tested your code, and it works fine without the ExifVersion line.  I don't know why you think this is necessary.

- Phil

...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

greybeard

When I change my script as suggested I find it deletes the non-blank tag and not the blank tag

Before:
$ exiftool -a -G1 -FileName -Instructions -ext psd DB-105000318_Blue_FT.psd
[System]        File Name                       : DB-105000318_Blue_FT.psd
[XMP-photoshop] Instructions                    : TechCloud
[XMP-photoshop] Instructions                    :


After:
$ exiftool -a -G1 -FileName -Instructions -ext psd DB-105000318_Blue_FT.psd
[System]        File Name                       : DB-105000318_Blue_FT.psd
[XMP-photoshop] Instructions                    :


Script:
#!/usr/bin/perl

use strict;
use warnings;
use Image::ExifTool;

my @tags = qw(Instructions);
my @image_files=`ls -1 DB-105000318_Blue_FT.psd`;
foreach my $file (@image_files) {
  chomp($file);
  my $exifTool = new Image::ExifTool;
  my $hash_ref = $exifTool->ImageInfo($file, \@tags);
  foreach my $tag (sort keys % {$hash_ref}) {
     my $val = $$hash_ref{$tag};
     if ($val eq "") {
        printf("%-50s %-10s blank tag removed\n",$file,$tag);
        $exifTool->SetNewValue($tag);
     }
  }
  $exifTool->WriteInfo($file);
}

Phil Harvey

There is something odd going on here because there should only be one XMP:Instuctions tag in a file.  Can you send me the file so I can take a look (philharvey66 at gmail.com)?

- Phil

Edit: Ah.  I see it was attached in an earlier post...  taking a look at it now.
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

greybeard

I used the file posted by the OP a couple of replies above mine.

There is definitely a problem with the files - that is why he had issues and I was trying to figure out a way to fix them.

Phil Harvey

Ah, OK:

% exiftool tmp -instructions -a -G5
======== tmp/DB-105000318_Blue_FT.psd
[PSD-XMP]       Instructions                    : TechCloud
[PSD-EXIFInfo-IFD0-XMP] Instructions            :


XMP shouldn't exist within the EXIFInfo of a PSD file.

And Greybeard is correct, ExifTool won't normally try to write this.  In fact, it is specifically blocked because I have seen instances where EXIF in a JPEG or TIFF image contains Photoshop information, which in turn contains EXIF leading to a possible infinite recursion.  I have since added more protection against infinite recursion, but I hesitate to change this because a false step here could mean a possible ExifTool hang.

So Greybeard's technique of forcing the EXIF to be written by conditionally removing a dummy EXIF value is necessary here to get ExifTool to process the EXIF.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Phil Harvey

I've seen another case like this where IPTC is written in PSD-EXIFInfo-IFD0-IPTC.  As a result, I am adding a patch to ExifTool 12.43 which will allow EXIF to be edited inside the Photoshop information of a PSD file without the need to write an EXIF tag.  Note that this won't apply to Photoshop information in JPG or TIFF files.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).