Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Adding Keywords

https://discussions.apple.com/thread/4609223?start=0&tstart=0


This is where I got to recently with a script many thanks to all that helped.


The issue I still have is that keywords don't get added to the files labelled AB12NW01234MU2MM_2


The way it works is to find the take the name of the file.

AB12NW01234MU2MM.psd (that is always 16 digits inc Extentsion)


It then checks against a CSV File,


AB12NW01234MU2MM.psd,AB12NW01234MU2MM,504123,Picture of a person,5


It then uses the line above to add the other data to the IPTC/Exif data of the file.


At the same time it still needs to add a checkmark to say that that image has been shot.


The above works with the script, however it does not cater for those images that have _2, _3, _4

With these it needs to do the same but only do it to add information to the file not add the tick mark.


Very difficult to perhaps understand the code, but I hope someone can help me. These are the handlers below




on findNameInCsv(f) -- search the exact name from the beginning of each line ***

set {tid, text item delimiters} to {text item delimiters, {":"}}

set tName to last text item of f -- get the filename

set text item delimiters to "."

set thisExt to last text item of tName-- get name extension

set text item delimiters to tid


if thisExt is in extension_list then

set tc to (count thisExt) + 2

set last3chars to text -(tc + 2) thru -tc of tName-- get last 3 characters before name extension--> _02

else -- no extension

set last3chars to text -3 thru -1 of tName-- get last 3 characters --> _02

end if


--*** true if "_02" .... "_12" ***--

tell last3chars to set b to it starts with "_" and (text 2 is "0" and text 3 is in "23456789" or text 2 thru 3 is in {"10", "11", "12"})

try

if b then set tSku to text 1 thru 16 of tName-- the begining 16 digits, I presume the first 16 characters in the nameon error

set b to false


end try





set n to tName & ","

set tc to counto'scsvText

repeat with i from 1 to tc

set t to item i of o's csvText

if not b and t starts with n or b and (t starts with tSku or t starts with "," & tSku) then -- found

set x to ""

if not b then set item i of o's csvText to "," & t

set text item delimiters to {","}

try

set x2 to text item 2 of t --get original Name

set x3 to (text item 3 of t) & "ALTERNATIVE CODE :_" --get alternative Sku

set x4 to text item 4 of t -- get the keyword

try

set x5 to text item 6 of t--get AIR OR SEA RECORD

on error

set x5 to ""

end try

end try

set text item delimiters to tid


-- exiftool add the keywords to EXIF


if x4 is not "" then do shell script "/usr/bin/exiftool -P -overwrite_original_in_place -keywords+=" & (quoted form of x4) & " -headline=" & (quoted form of x2) & " -source=" & (quoted form of x5) & " " & quoted form of POSIX path of f


return (not b)

end if

end repeat

return false

end findNameInCsv


on write_to_file(the_file, tList) -- update CSV file ***

set n to 0

set n1 to 0

set tc to counto'scsvText

repeat with i from 1 to tc--- ** move lines with check mark to the bottom **

set L to item i of o's csvText

if L is not "" then -- not a blank lines

set n1 to n1 + 1 -- count this valid line

if "" is in L then

set n to n + 1 -- count this check mark

set end of o's csvText to L

set item i of o's csvText to missing value

end if

else

set itemi of o'scsvText to missing value-- remove this blank lines

end if

end repeat

set {tid, text item delimiters} to {text item delimiters, {return}}

set the_data to (text of o'scsvText) as text-- convert list of lines to text

set text item delimiters to tid

try

set openfile to open for accessthe_file with write permission

set eof of openfile to 0


writethe_datatoopenfilestarting at 0 as «class utf8»


close accessopenfile

on error

try


close accessthe_file

end try

end try

return n1 = n-- if the number of lines equal the numbers of check marks

end write_to_file


Mac Pro, OS X Mavericks (10.9)

Posted on Nov 28, 2013 8:45 AM

Reply
16 replies

Nov 29, 2013 4:20 AM in response to MattJayC

I've been trying to understandsome more and there is one line I believe to have incorrect logic, and I still cant see it? Maybe it needs () or something to make it work


I've looked at it again and attempted to add more english to help it make sence..


on findNameInCsv(f) -- search the exact name from the beginning of each line ***

set {tid, text item delimiters} to {text item delimiters, {":"}}

set tName to last text item of f -- get the filename

set text item delimiters to "."

set thisExt to last text item of tName-- get name extension

set text item delimiters to tid



if thisExt is in extension_list then

set tc to (count thisExt) + 2

set last2chars to text -(tc + 1) thru -tc of tName-- get last 2 characters before name extension--> _02

else -- no extension

set last2chars to text -2 thru -1 of tName-- get last 2 characters --> _02

end if


--*** true if "_02" .... "_12" ***--

tell last2chars to set b to it starts with "_" and (text 2 is in "23456789")


loglast3chars

try

if b then set tSkuLineofFile to text 1 thru 16 of tName-- the begining 16 digits, I presume the first 16 characters in the nameon error

set b to false


end try




set FullNamenComma to tName & ","

set tc to counto'scsvText

repeat with i from 1 to tc

set t to item i of o's csvText



--I think it gets stuck here, when the file is labelled AB15NW01234BU5AG_2.psd (_2 as the main difference) it skips where it should look up the 'tSkuLineofFile' from the CSV File, in the CSV file it may have a by it but still needs to gather the keywords to pass on to the rest of script to have exiftool stamp it.


if not b and t starts with FullNamenComma or b and (t starts with tSkuLineofFile or t starts with "," & tSkuLineofFile) then -- found




set x to ""

if not b then set item i of o's csvText to "," & t

set text item delimiters to {","}

try

set x2 to text item 2 of t --get original Name

set x3 to (text item 3 of t) & "ALTERNATIVE CODE :_" --get alternative Sku

set x4 to text item 4 of t -- get the keyword

try

set x5 to text item 6 of t--get AIR OR SEA RECORD

on error

set x5 to ""

end try

end try

set text item delimiters to tid


-- exiftool add the keywords to EXIF


if x4 is not "" then do shell script "/usr/bin/exiftool -P -overwrite_original_in_place -keywords+=" & (quoted form of x4) & " -headline=" & (quoted form of x2) & " -source=" & (quoted form of x5) & " " & quoted form of POSIX path of f


return (not b)

end if

end repeat

return false

end findNameInCsv

Nov 30, 2013 9:52 AM in response to MattJayC

This is how it now looks, like i mentioned I've tried to make it more understadable and it now adds keywords to the _2 images but now doesn't add a tick for those without the _2,


on findNameInCsv(f) -- search the exact name from the beginning of each line ***

set {tid, text item delimiters} to {text item delimiters, {":"}}

set tName to last text item of f -- get the filename

log "f filepath; " & f

log "tName; " & tName

set text item delimiters to "."

set thisExt to last text item of tName-- get name extension

log "thisExt; " & thisExt

set text item delimiters to tid


if thisExt is in extension_list then

set tc to (count thisExt) + 2

log "tc " & tc

set suffix to text -(tc + 1) thru -tc of tName-- get last 3 characters before name extension--> _02

log "suffix Route A; " & suffix

else -- no extension

set suffix to text -2 thru -1 of tName-- get last 3 characters --> _02

log "suffix Route B; " & suffix

end if


--*** true if "_02" .... "_12" ***--

tell suffix to set b to it starts with "_" and (text 2 is in "23456789")

log "b Route A; " & b



(*try

if b then set sku_only to text 1 thru 16 of tName -- the begining 16 digits, I presume the first 16 characters in the nameon error

set b to false

log "b Route B; " & b

log "Sku_only; " & sku_only

end try*)



set WholenameComma to tName & ","


try

if suffix begins with "_" then set WholenameComma to (text 1 thru 16 of tName & ".PSD,") -- the begining 16 digits, I presume the first 16 characters in the nameon error

set b to true

log "b Route B; " & b

log "Sku_only; " & WholenameComma

end try


log "WholenameComma; " & WholenameComma

set tc to counto'scsvText

repeat with i from 1 to tc

set aRowinSkulist to itemi of o'scsvText

log "aRowinSkulist; " & aRowinSkulist


if not b and aRowinSkulist starts with WholenameComma or b and (aRowinSkulist starts with WholenameComma or aRowinSkulist starts with "," & WholenameComma) then -- found

set x to "" -- Not sure of its purpose


if not b then set item i of o's csvText to "," & aRowinSkulist

set text item delimiters to {","}

try

set headline2 to text item 2 of aRowinSkulist--get original Name

set x3 to (text item 3 of aRowinSkulist) & "ALTERNATIVE CODE :_" --get alternative Sku

set keyword4 to text item 4 of aRowinSkulist-- get the keyword

try

set WeekNumber5 to text item 6 of aRowinSkulist--get AIR OR SEA RECORD

on error

set WeekNumber5 to ""

end try

end try

set text item delimiters to tid


-- exiftool add the keywords to EXIF


if keyword4 is not "" then do shell script "/usr/bin/exiftool -P -overwrite_original_in_place -keywords+=" & (quoted form of keyword4) & " -headline=" & (quoted form of headline2) & " -source=" & (quoted form of WeekNumber5) & " " & quoted form of POSIX path of f


return (not b)

end if

end repeat

return false

end findNameInCsv

Dec 2, 2013 7:19 PM in response to MattJayC

Hello


The original code won't handle _2 suffix correctly because it is expecting _02 suffix. Another thing to note is that it is not appropriate to add new field of check mark to particular record in CSV because it results in mal-formed CSV which should have the same number of fields in every record.


Anyway, if I'm not mistaken, the following handler(s) will address the first problem, i.e., suffix processing. You need to replace the original findNameInCSV() handler with the new findNameInCSV() handler and the general purpose _split() handler. The statements other than those handlers in the code below are for testing.


script o
    property csvText : {"AB12NW01234MU2MM.psd,AB12NW01234MU2MM,504123,Picture of a person,5"}
    --property csvText : {"✔,AB12NW01234MU2MM.psd,AB12NW01234MU2MM,504123,Picture of a person,5"}
end script
set f to "path:to:AB12NW01234MU2MM_2.psd"
--set f to "path:to:AB12NW01234MU2MM.psd"
findNameInCSV(f)

on findNameInCSV(f)
    (*
        string f : HFS path of file
        return boolean : true if csv file is modified, false otherwise
    *)
    set fname to _split(":", f)'s item -1 -- filename
    tell _split(".", fname)
        if (count) > 1 then -- extensions exists
            set stem to "" & items 1 thru -2 -- name stem
            set ext to "." & item -1 -- name extension including leading period
        else
            set stem to fname
            set ext to ""
        end if
    end tell
    tell _split("_", stem)
        if (count) > 1 then
            set base to "" & items 1 thru -2 -- name stem w/o suffix
            set suffix to "_" & item -1 -- suffix including leading _
        else
            set base to stem -- name stem w/o suffix
            set suffix to ""
        end if
    end tell
    --log {fname, stem, ext, base, suffix} -- # for test
    
    set _modified to false
    set _has_suffix to suffix ≠ ""
    set n to base & ext
    set tc to count o's csvText
    repeat with i from 1 to tc
        set t to o's csvText's item i
        if not _has_suffix and t starts with n or _has_suffix and (t starts with n or t starts with "✔," & n) then -- found
            if not _has_suffix then
                set item i of o's csvText to "✔," & t -- modify csvText
                set _modified to true
            end if
            if t starts with "✔," then
                set delta to 1 -- field offset (this is required because field length in record is not constant)
            else
                set delta to 0
            end if
            set x4 to ""
            tell _split(",", t)
                try
                    set x2 to item (2 + delta) --get original name
                    set x3 to item (3 + delta) --get alternative Sku
                    set x4 to item (4 + delta) -- get the keyword
                    try
                        set x6 to item (6 + delta) --get AIR OR SEA RECORD
                    on error
                        set x6 to ""
                    end try
                end try
            end tell
            --log o's csvText -- # for test
            --log {x2, x3, x4, x6} -- # for test
            
            -- exiftool add the keywords to EXIF
            if x4 ≠ "" then do shell script "/usr/bin/exiftool -P -overwrite_original_in_place -keywords+=" & (quoted form of x4) & " -headline=" & (quoted form of x2) & " -source=" & (quoted form of x6) & " " & quoted form of POSIX path of f
            return _modified
        end if
    end repeat
    return _modified
end findNameInCSV

on _split(d, t)
    (*
        string or list d : separator(s)
        string t : source string
        return list : t splitted by d
    *)
    local astid0, tt
    try
        set {astid0, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {} & d}
        set tt to t's text items
        set AppleScript's text item delimiters to astid0
    on error errs number errn
        set AppleScript's text item delimiters to astid0
        error errs number errn
    end try
    return tt
end _split



By the way, it might be better to use more suitable handler name such as processNameInCSV() than findNameInCSV().


Hope this may help,

H

Jun 16, 2015 12:11 PM in response to Hiroto

Hi Hiroto, can you help me again?


I'm still using the above keyword renamer, however I had to add a different rule to the list, this involves the file name looking like this


MM__OEmj123AB.PSD

or

MM__OEmj123AB_2.PSD


I hope you remember the nature of the way it worked, it used applescript delimiters of '_' as you can see I chose to use a double underscore as a result it fails to match the code. is it possible to make it work still?

Jun 24, 2015 3:05 AM in response to MattJayC

Hello


Sorry for late reply. Didn't notice this thread has been revived lately.


You'd need to rewrite code to parse file name. Here's one way.


Replace the first 19 lines of findNameInCSV() handler, which parses file name using _split():



on findNameInCSV(f) (* string f : HFS path of file return boolean : true if csv file is modified, false otherwise *) set fname to _split(":", f)'s item -1 -- filename tell _split(".", fname) if (count) > 1 then -- extensions exists set stem to "" & items 1 thru -2 -- name stem set ext to "." & item -1 -- name extension including leading period else set stem to fname set ext to "" end if end tell tell _split("_", stem) if (count) > 1 then set base to "" & items 1 thru -2 -- name stem w/o suffix set suffix to "_" & item -1 -- suffix including leading _ else set base to stem -- name stem w/o suffix set suffix to "" end if end tell -- # REST OMITTED: NOT MODIFIED end findNameInCSV



with the following one line and add new re_match() handler to parse file name more flexibly:



on findNameInCSV(f) (* string f : HFS path of file return boolean : true if csv file is modified, false otherwise *) set {fname, stem, base, suffix, ext} to re_match("(([^:]*?)(_[0-9]+)?)(\\.[^.:]+)?$", f) & {"", "", "", "", ""} -- # REST OMITTED: NOT MODIFIED end findNameInCSV on re_match(re, argv) (* string re : regexp pattern string argv : source text return list : list of regexp matches for {$&, $1, $2, ...} for source text *) set args to "" repeat with a in {re} & argv set args to args & space & a's quoted form end repeat set r to do shell script "/usr/bin/perl -CSDA -w <<'EOF' - " & args & " use strict; my $re = shift; (my $s = shift) =~ /$re/o; my ($i, $j, $k) = (0, 0, length $s); local $, = qq(\\x1c); print map { ($i, $j) = ($-[$_], $+[$_]); defined $i && $j <= $k ? substr($s, $i, $j - $i) : '' } 0..$#-; EOF" without altering line endings set fs to character id 28 -- U+00!C try set {astid0, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {fs}} set rr to r's text items set AppleScript's text item delimiters to astid0 return rr on error errs number errn set AppleScript's text item delimiters to astid0 error errs number errn end try end re_match




Hope this may help,

H

May 11, 2016 6:53 AM in response to Hiroto

I have CSV file that I copy from the network drive.



They are labeled brand_WK35.csv

The WK number changes each week.

They are in this format

SKU.PSD,SKU,AlternativeCode,Keywords


or in realterms

DJ30ER08256MU4MM.PSD,DJ30ER08256MU4MM,49850715,Engraved Disc Drop Earring,


There are multiple brand folders. they are located here

tell application "Finder" to set CompletedFolder to folder (((path tostartup disk) as text) & "Volumes:CloudStorage:Dropbox:CompletedFolders:")

Each folder in the above folder is labelled brand_WK35_PSD


In these folders are the images.


Some images with the SKU have more than one image these are labelled with the suffix _2,_3, etc.


This script is design to run everytime a file arrives in the folder (folder actions)


The script needs to add the metadata to each image, correctly placing the relevant information in the correct catagory, using exiftool.

This needs to be done for each brand folder with its csv file. corresponding to the week number.


SKU goes to -headline

alternative Sku & suffix to -instructions (i.e. the image labelled DJ30ER08256MU4MM_2.PSD would have exiftool set the -instructions to 49850715_2)

keywords to -XMP:subject


The original CSV file would also need updating.

If the primary image is found then a checkmark should be placed at the beginning of the line(previously I used ","butitmaybemoresuitabletouse"YES," It should NOT get a tick if only the "_2" etc files are found but their metadata should be updated still.


A problem with the previous script that I attempted to update (HERE) if the primary image is added first, the script runs and the metadata is applied and the csv file is updated with a checkmark, then when the _2 image arrives it does not get the metadata applied but should.


What would be useful at this stage is if the folder contained images that are NOT in the csv file then these would be moved to a sub folder called "no metadata provided"


Included in this script I have a ratio checker that makes sure that the images are the correct size. and then labels them as I have in the previous script.


I hope this is all makes sense I can also provide you some sample material if you need it.



Many thanks


Matt




May 14, 2016 7:40 AM in response to MattJayC

Hello


As far as I can tell after reading through your updated script, it should work as you think it should.


However, one thing to note is that it is NOT written as a folder action script. So I'd suspect that it may not be triggered oftentimes. And indeed I'd not be surprised to see it is not triggered as expected even if it is written as a proper folder action script because folder action is totally unreliable in my experiences.


To test the theory, try running the script manually when you suspect something is wrong and see what happens or not.


Regards,

H

May 18, 2016 9:40 PM in response to MattJayC

Hello


If I understand it correctly, you might revise the script as follows.


I marked modified or added parts by "######## MODIFIED ########" or "######## ADDED ########" in code. (Currently a file is considered found in CSV regardless whether it is already check marked or not.)



--APPLESCRIPT (PART) on KeyworderChecker(BrandName, Ratio, CompletedFolder) try tell application "Finder" to set the_Folders to (get every folder of CompletedFolder whose name starts with BrandName) if the_Folders is not {} then -- # code omitted if filesOfFolder is not {} then -- # code omitted repeat with i from 1 to the count of filesOfFolder set t_path to (item i of filesOfFolder) as string -- # code omitted -- *** find this name in CSV text *** -- ###### MODIFIED ###### if existsCSV then set {_found, _modified} to my findNameInCsv(t_path) set isChanged to _modified -- a check mark was added in CSV text *** if not _found then -- change label to orange tell application "Finder" to set label index of file t_path to 1 end if end if end repeat if existsCSV then -- # code omitted end if end if end if on error error_message -- # code omitted end try end KeyworderChecker on findNameInCsv(f) (* string f : HFS path of file return list : {_found, _modified} -- ###### MODIFIED ###### (boolean) _found : true if f's name is found in csv file, false otherwise (boolean) _modified : true if csv file is modified, false otherwise *) set fName to _split(":", f)'s item -1 -- filename tell _split(".", fName) if (count) > 1 then -- extensions exists set stem to "" & items 1 thru -2 -- name stem set ext to "." & item -1 -- name extension including leading period else set stem to fName set ext to "" end if end tell tell _split("_", stem) if (count) > 1 then set base to "" & items 1 thru -2 -- name stem w/o suffix set suffix to "_" & item -1 -- suffix including leading _ else set base to stem -- name stem w/o suffix set suffix to "" end if end tell --log {fname, stem, ext, base, suffix} -- # for test set _modified to false set _found to false -- ###### ADDED ###### set _has_suffix to suffix ≠ "" set n to base & ext set tc to count o's csvText repeat with i from 1 to tc set t to o's csvText's item i set _found to _found or (t starts with n or t starts with "✔," & n) -- ###### ADDED ###### if not _has_suffix and t starts with n or _has_suffix and (t starts with n or t starts with "✔," & n) then -- found if not _has_suffix then set item i of o's csvText to "✔," & t -- modify csvText set _modified to true end if if t starts with "✔," then set delta to 1 -- field offset (this is required because field length in record is not constant) else set delta to 0 end if set x4 to "" tell _split(",", t) try set x2 to (item (2 + delta) & suffix) --get original name set x3 to (item (3 + delta) & suffix) --get alternative Sku set x4 to item (4 + delta) -- get the keyword try set x6 to item (5 + delta) --get AIR OR SEA RECORD on error set x6 to "" end try end try end tell --log o's csvText -- # for test log {x2, x3, x4, x6, suffix} -- # for test set modDate to (do shell script "/usr/local/bin/exiftool -s3 -q -filemodifydate " & quoted form of POSIX path of f) -- exiftool add the keywords to EXIF if stem begins with "GT" then if suffix is equal to "" then set GTsuffix to "01" else try set GTsuffix to ("0" & (character 2 of suffix)) as text set x3 to ((characters 1 thru 12 of x3) & GTsuffix as text) on error errMsg log {"errMsg = " & errMsg} end try end if end if log {"x3_" & x3} try --if x4 ≠ "" then do shell script "/usr/local/bin/exiftool -a -api PNGEarlyXMP -overwrite_original_in_place -XMP:subject=" & (quoted form of x4) & " -headline=" & (quoted form of x2) & " -instructions=" & (quoted form of x3) & " -source=" & (quoted form of x6) & " " & quoted form of POSIX path of f --end if on error errMsg log {"errMsg " & errMsg} end try do shell script "/usr/local/bin/exiftool -api PNGEarlyXMP -overwrite_original_in_place -filemodifydate=" & (quoted form of modDate) & " " & quoted form of POSIX path of f end if end repeat return {_found, _modified} -- ###### MODIFIED ####### end findNameInCsv --END OF APPLESCRIPT (PART)



Good luck,

H

Adding Keywords

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.