MattJayC

Q: Get list of layer names from PSD file.

This the script I  am using, it gets a list of the layer names of a PSD file.

 

I am just trying to find out if the layer contains the named layer "Main Image"

 

But my logic appears not to be working.

Any ideas please.

 

set this_item to (choose file with prompt "Choose file to record path name") as string

 

set nLayersName to my getNameOfLayers(this_item as string)

log nLayersName as text

if "Main Image" is in {(nLayersName as text)} then

  display dialog "Do something"

end if

 

 

on getNameOfLayers(f)

  ((do shell script "/usr/bin/mdls -name kMDItemLayerNames " & (quoted form of POSIX path of f)))

end getNameOfLayers

Posted on Mar 11, 2015 4:47 AM

Close

Q: Get list of layer names from PSD file.

  • All replies
  • Helpful answers

Page 1 Next
  • by VikingOSX,

    VikingOSX VikingOSX Mar 11, 2015 6:33 AM in response to MattJayC
    Level 7 (21,056 points)
    Mac OS X
    Mar 11, 2015 6:33 AM in response to MattJayC

    This works for me on a four layer photoshop image. Note. the do shell script returns the layers in a list starting with the bottom layer.

     

    set this_item to POSIX path of (choose file with prompt "Choose file to record path name")

     

    set nLayersName to {}

    set matchLayer to "Main Image"

     

    set nLayersName to getNameOfLayers(this_item)

    log nLayersName as text

     

    if isMatchLayer(nLayersName, matchLayer) then

       display dialog "Matched " & matchLayer

    else

       display dialog "Layer " & matchLayer & " not found."

    end if

     

    on getNameOfLayers(f)

     

         set matchCmdStr to " | egrep -io '(\".+\")'"

         set mdlsCmd to "mdls -name kMDItemLayerNames "

     

         return do shell script (mdlsCmd & f's quoted form & matchCmdStr)

     

    end getNameOfLayers

     

    on isMatchLayer(psdLayers, matchItem)

     

         set matched to false as boolean

     

         repeat with layer in paragraphs of psdLayers

              if matchItem is in layer then

                  set matched to true

              end if

         end repeat

     

         return matched

     

    end isMatchLayer

  • by MattJayC,

    MattJayC MattJayC Mar 11, 2015 6:46 AM in response to VikingOSX
    Level 1 (5 points)
    Desktops
    Mar 11, 2015 6:46 AM in response to VikingOSX

    That does work for me,

     

    I had a look to see if it saw all the files of my file and it doesn't its got some layer sets (groups).

     

    You can see the file here

     

    Thanks

     

    Matt

  • by VikingOSX,

    VikingOSX VikingOSX Mar 11, 2015 10:02 AM in response to MattJayC
    Level 7 (21,056 points)
    Mac OS X
    Mar 11, 2015 10:02 AM in response to MattJayC

    This will look for all occurrences of your match string, and return a match boolean and match count. Using your .psd file, the output of the AS is the following:

     

    Screen Shot 2015-03-11 at 12.58.08 PM.png

    Updated AppleScript

     

    set this_item to POSIX path of (choose file with prompt "Choose file to record path name")

     

    set nLayersName to {}

    set matchList to {}

    set matchLayer to "Main Image"

     

    set nLayersName to getNameOfLayers(this_item)

    log nLayersName as text

     

    set matchList to isMatchLayer(nLayersName, matchLayer)

    if item 1 of matchList then

        display dialog "Matched " & matchLayer & space & (item 2 of matchList) & " times."

    else

        display dialog "Layer " & matchLayer & " not found."

    end if

     

    on getNameOfLayers(f)

     

         set matchCmdStr to " | egrep -io '(\".+\")'"

         set mdlsCmd to "mdls -name kMDItemLayerNames "

     

         return do shell script (mdlsCmd & f's quoted form & matchCmdStr)

     

    end getNameOfLayers

     

    on isMatchLayer(psdLayers, matchItem)

     

         set matched to false as boolean

         set matchCount to 0 as integer

     

         repeat with layer in paragraphs of psdLayers

             if matchItem is in layer then

                 set matchCount to matchCount + 1

                 set matched to true

             end if

         end repeat

     

         return {matched, matchCount}

     

    end isMatchLayer

  • by VikingOSX,

    VikingOSX VikingOSX Mar 11, 2015 10:54 AM in response to VikingOSX
    Level 7 (21,056 points)
    Mac OS X
    Mar 11, 2015 10:54 AM in response to VikingOSX

    I just realized that the following had to be updated to return *all* layer names – quoted, and unquoted. It looks for anything in quotes, or any alphanumeric string. Finally, it simply excludes the kMDItemLayerNames line from the result.

     

    set matchCmdStr to " | egrep -io '(\".+\"|[[:alnum:]]+)' | egrep -v 'kMDItemLayerNames'"

  • by VikingOSX,

    VikingOSX VikingOSX Mar 11, 2015 1:59 PM in response to VikingOSX
    Level 7 (21,056 points)
    Mac OS X
    Mar 11, 2015 1:59 PM in response to VikingOSX

    This one is for Bob Harris if he happens to be looking. The following will do exactly what the revised matchCmdStr does. Basically, it says ignore any lines that match the regular expression (the double \\ is to appease AppleScript), print the others, and the second awk removes the leading white space for nice left flush returns.

     

    set matchStr to " | awk '!/kMDItemLayerNames|\\)/' | awk '{$1=$1}1' "

  • by VikingOSX,

    VikingOSX VikingOSX Mar 11, 2015 2:20 PM in response to VikingOSX
    Level 7 (21,056 points)
    Mac OS X
    Mar 11, 2015 2:20 PM in response to VikingOSX

    Or cleaner still, remove any leading whitespace.

     

    set matchStr to " | awk '!/kMDItemLayerNames|\\)/ { sub(/[ \t]+/, \"\"); print }' "

  • by MattJayC,

    MattJayC MattJayC Mar 12, 2015 9:37 AM in response to VikingOSX
    Level 1 (5 points)
    Desktops
    Mar 12, 2015 9:37 AM in response to VikingOSX

    Many Thanks

     

    that works a treat, allows me to see the Shadows layer too.

     

    Matt

  • by VikingOSX,

    VikingOSX VikingOSX Mar 12, 2015 10:28 AM in response to MattJayC
    Level 7 (21,056 points)
    Mac OS X
    Mar 12, 2015 10:28 AM in response to MattJayC

    Glad to help. Using Affinity Designer and Photo here myself.

     

    The following Terminal command will show the Photoshop files that have a  Shadow layer in them.

     

    mdfind -onlyin ~/Downloads -name 'kMDItemLayerNames == "*Shadow*"cdw && kMDItemContentType == "*photoshop*"cdw' "

     

    Result: DV25NW07779MU3GO.PSD

  • by MattJayC,

    MattJayC MattJayC Mar 13, 2015 4:57 AM in response to VikingOSX
    Level 1 (5 points)
    Desktops
    Mar 13, 2015 4:57 AM in response to VikingOSX

    I'm still trying to apply this in my script.

     

    The error I get

     

    Result:

    error "Finder got an error: Can’t continue getNameOfLayers." number -1708

     

    I've added the handlers

     

    This is the script.

     

    tell application "Finder"

      set HotDestination to (((path to pictures folder) as text) & "HotDestination")

      set HotFolder2do to (((path to pictures folder) as text) & "HotFolder2do")

      set HotFolderDone to (((path to pictures folder) as text) & "HotFolderDone")

     

     

      repeat with tFile in (get document files of folder HotDestination whose name extension is in extension_list and (name does not start with "50" or name does not start with "MJC"))

     

      set nLayersName to getNameOfLayers(tFile)

      set matchList to isMatchLayer(nLayersName, matchLayer)

      if item 1 of matchList then

      move tFile to the folder HotFolderDone -- move to subFolder A

      else

      move tFile to the folder HotFolder2do

      end if

     

      end repeat

    end tell


  • by VikingOSX,

    VikingOSX VikingOSX Mar 13, 2015 6:11 AM in response to MattJayC
    Level 7 (21,056 points)
    Mac OS X
    Mar 13, 2015 6:11 AM in response to MattJayC

    If you are using this matchCmdStr, AppleScript syntax annoyances want the tab indicator to be escaped as \\t. This little detail would blow up getNameOfLayers(). My bad.

     

    set matchCmdStr to " | awk '!/kMDItemLayerNames|\\)/ { sub(/[ \t]+/, \"\"); print }' "

  • by MattJayC,

    MattJayC MattJayC Mar 13, 2015 7:08 AM in response to VikingOSX
    Level 1 (5 points)
    Desktops
    Mar 13, 2015 7:08 AM in response to VikingOSX

    Not sure thats the issue, I think it might be to do with the way the file is being located.

     

    repeat with tFile in (get document files of folder HotDestination whose name extension is in extension_listand (name does not start with "50" or name does not start with "MJC"))


    There can be more than one file in the folder, so it would need to check and move each one?



  • by VikingOSX,

    VikingOSX VikingOSX Mar 13, 2015 8:09 AM in response to MattJayC
    Level 7 (21,056 points)
    Mac OS X
    Mar 13, 2015 8:09 AM in response to MattJayC

    In your code is there a space between extension_list and the word "and?"

     

    Screen Shot 2015-03-13 at 11.07.37 AM.png

  • by MattJayC,

    MattJayC MattJayC Mar 13, 2015 8:42 AM in response to VikingOSX
    Level 1 (5 points)
    Desktops
    Mar 13, 2015 8:42 AM in response to VikingOSX

    Here is how I am using it. In full

     

    There was a space on the original code.

    property type_list : {"TIFF", "JPEG", "PNGf", "PICT"}

    property extension_list : {"tif", "tiff", "jpg", "jpeg", "png", "pict", "psd"}

     

    set nLayersName to {}

    set matchList to {}

    set matchLayer to "Shadows"

     

    tell application "Finder"

      set HotDestination to (((path to pictures folder) as text) & "HotDestination")

      set HotFolder2do to (((path to pictures folder) as text) & "HotFolder2do")

      set HotFolderDone to (((path to pictures folder) as text) & "HotFolderDone")

     

     

      repeat with tFile in (get document files of folder HotDestination whose name extension is in extension_list and (name does not start with "50" or name does not start with "MJC"))

     

      set nLayersName to getNameOfLayers(tFile)

      set matchList to isMatchLayer(nLayersName, matchLayer)

      if item 1 of matchList then

      move tFile to the folder HotFolderDone -- move to subFolder A

      else

      move tFile to the folder HotFolder2do

      end if

     

      end repeat

    end tell

     

     

     

     

     

     

     

     

    on getNameOfLayers(f)

     

      set matchCmdStr to " | awk '!/kMDItemLayerNames|\\)/ { sub(/[ ]+/, \"\"); print }' "

     

      set mdlsCmd to "mdls -name kMDItemLayerNames "

     

      return do shell script (mdlsCmd & f's quoted form & matchCmdStr)

     

    end getNameOfLayers

     

    on isMatchLayer(psdLayers, matchItem)

     

      set matched to false as boolean

      set matchCount to 0 as integer

     

      repeat with layer in paragraphs of psdLayers

      if matchItem is in layer then

      set matchCount to matchCount + 1

      set matched to true

      end if

      end repeat

     

      return {matched, matchCount}

     

    end isMatchLayer

  • by VikingOSX,

    VikingOSX VikingOSX Mar 13, 2015 10:15 AM in response to MattJayC
    Level 7 (21,056 points)
    Mac OS X
    Mar 13, 2015 10:15 AM in response to MattJayC

    Is your script now working correctly?

     

    What happens if tFile is not found/set in that repeat clause logic? Passing an undefined tFIle into the getNameOfLayers function would wreak havoc. I would test for a valid tFile before passing it into the getNameOfLayers function.

Page 1 Next