Hello,
I’m trying to write a script that checks images in a folder and labels the images red if they are less than 1500 pixels width or height.
here is what i have so far:
set startFolder to (choose folder with prompt "Choose a folder of images you want to check")
tell application "Finder" to set fileList to every file in folder startFolder
set minValue to 1500
repeat with aFile in fileList
tell application "Image Events"
-- start the Image Events application
launch
-- open the image file
set thisImage to open aFile
set the props_rec to the properties of thisImage
close thisImage
-- extract the property value
copy (dimensions of props_rec) to {x, y}
if x is less than minValue then
tell application "Finder" to set label index of file (startFolder & fileName) to 2
end if
if y is less than minValue then
tell application "Finder" to set label index of file (startFolder & fileName) to 2
end if
end tell
end repeat
I’m getting: error “The variable thisImage is not defined.” number -2753 from “thisImage”
I’ve defined “thisImage” as the current open image file. So why does it say that it’s not defined?
Also, I set up two if statements to check the width and height. There’s gotta be a more concise/better way to do that.
You are asking ImageEvents to open a file defined by a Finder Reference which it can’t treat.
set startFolder to (choose folder with prompt "Choose a folder of images you want to check")
tell application "Finder" to set fileList to every file in folder startFolder
set minValue to 1500
repeat with aFile in fileList
set aFile to aFile as alias # coerce the Finder reference into an alias which is a known object for ImageEvents
tell application "Image Events"
-- start the Image Events application
launch
-- open the image file
set thisImage to open aFile
set the props_rec to the properties of thisImage
close thisImage
-- extract the property value
copy (dimensions of props_rec) to {x, y}
if x is less than minValue then
-- tell application "Finder" to set label index of file (startFolder & fileName) to 2 # FileName is not defined here
tell application "Finder" to set label index of aFile to 2
end if
if y is less than minValue then
-- tell application "Finder" to set label index of file (startFolder & fileName) to 2 # FileName is not defined here
tell application "Finder" to set label index of aFile to 2
end if
end tell
end repeat
Yvan KOENIG running Sierra 10.12.3 in French (VALLAURIS, France) mercredi 25 janvier 2017 17:54:12
-------------------------------------------------------------------------------------------
# User Settings:
-------------------------------------------------------------------------------------------
set imageFolderPath to "~/test_directory/Image_Test_Folder/"
set labelIndex to 6
-------------------------------------------------------------------------------------------
tell application "System Events" to set imageFolderPath to POSIX path of disk item imageFolderPath
set imageFolderHFS to ((POSIX file imageFolderPath) as alias) as text
set shCMD to "
cd " & quoted form of imageFolderPath & "
mdls -name kMDItemFSName -name kMDItemPixelWidth -name kMDItemPixelHeight * | sed -E 's!^.+= !!; s!\"!!g'
"
set dataList to paragraphs of (do shell script shCMD)
tell application "Finder"
repeat with i from 1 to (length of dataList) by 3
set {fileName, pixelHeight, pixelWidth} to (items i thru (i + 2) of dataList)
if (pixelHeight as integer < 1500) or (pixelWidth as integer < 1500) or (pixelHeight = "(null)") or (pixelWidth = "(null)") then
set theFile to (imageFolderHFS & fileName) as alias
set label index of theFile to labelIndex
end if
end repeat
update alias imageFolderHFS
end tell
-------------------------------------------------------------------------------------------
Edit 2017/01/28 07:47 CST:
¢ Changed ˜ kMDItemDisplayName’ to ˜kMDItemFSName’ “ per Shane Stanley’s advice.
Edit 2017/01/28 08:25 CST:
¢ Allowed for NULL pixel width and heights “ again per Shane’s advice.
¢ Made the user-settings a little more obvious.
Yep – but doesn’t mdls return a recursive result? That might be overkill of a different sort.
Later…
There are a couple of other issues, too. The name being returned won’t match if you have extensions always showing but it’s been set to hidden for a file – I think you need to use kMDItemPath instead. And it probably needs to allow for files with a pixelHeight and width of “(null)”.
set imageFolderPath to "~/test_directory/Image_Test_Folder/"
tell application "System Events" to set imageFolderPath to POSIX path of disk item imageFolderPath
set imageFolderHFS to ((POSIX file imageFolderPath) as alias) as text
with
set imageFolderHFS to (path to home folder as text) & "test_directory:Image_Test_Folder:"
set imageFolderPath to POSIX path of imageFolderHFS
Hey all,
So, I tried StefanK’s changes to ccstones. Returns an error:
error “Can’t make {alias "Macintosh HD:Users:admin:Desktop:Incoming Images:Raw:2017-01-13:", "1000-2475.png"} into type alias.” number -1700 from {alias “Macintosh HD:Users:admin:Desktop:Incoming Images:Raw:2017-01-13:”, “1000-2475.png”} to alias
now, It’s not always going to be the same folder so, i modified it to choose the folder.
set labelIndex to 6
set imageFolderHFS to (choose folder with prompt "Choose a folder of images you want to check")
set imageFolderPath to POSIX path of imageFolderHFS
set shCMD to "
cd " & quoted form of imageFolderPath & "
mdls -name kMDItemDisplayName -name kMDItemPixelWidth -name kMDItemPixelHeight * | sed -E 's!^.+= !!; s!\"!!g'
"
set dataList to paragraphs of (do shell script shCMD)
tell application "Finder"
repeat with i from 1 to (length of dataList) by 3
set {fileName, pixelHeight, pixelWidth} to (items i thru (i + 2) of dataList)
if pixelHeight as integer < 1500 or pixelWidth as integer < 1500 then
set theFile to (imageFolderHFS & fileName) as alias
set label index of theFile to labelIndex
end if
end repeat
update alias imageFolderHFS
end tell
You are trying to concatenate two items which you can’t.
set theFile to (imageFolderHFS & fileName) as alias
As you (me too) aren’t allowed to concatenate these objects you get a list : {alias "Macintosh HD:Users:admin:Desktop:Incoming Images:Raw:2017-01-13:", "1000-2475.png"} which means nothing usable.
I repeat that you (me too) must coerce the first component into a string (text means the same).
set theFile to ((imageFolderHFS as text) & fileName) as alias
I guess that you missed the fact that choose folder returns an alias, not a string.
From my point of view there is a better scheme. At the very beginning, use :
set imageFolderHFS to (choose folder with prompt "Choose a folder of images you want to check") as text
The two added words make the difference.
The instruction used just below :
set imageFolderPath to POSIX path of imageFolderHFS
Apply flawlessly upon a path defined by a string
With that, in your loop you will no longer have to repeatedly coerce an alias into a string because the variable imageFolderHFS would be already a text object.
I hope that this time you will understand why you got odd results.
Yvan KOENIG running Sierra 10.12.3 in French (VALLAURIS, France) jeudi 26 janvier 2017 15:54:09
This is a variation on Chris’s approach – it ignores files in subfolders, and handles hidden extensions and files without width and height values. It’s also uses ASObjC rather than shell scripting and Finder.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
-- build search folder URL
set folderPath to POSIX path of (choose folder)
set theURL to current application's |NSURL|'s fileURLWithPath:folderPath
if folderPath ends with "/" then set folderPath to text 1 thru -2 of folderPath -- used later to eliminate nested files
-- some house-keeping; resolves these keys once to save time later
set NSMetadataItemPathKey to current application's NSMetadataItemPathKey
set NSMetadataItemPixelWidthKey to current application's NSMetadataItemPixelWidthKey
set NSMetadataItemPixelHeightKey to current application's NSMetadataItemPixelHeightKey
set NSURLLabelNumberKey to current application's NSURLLabelNumberKey
set requiredKeys to {NSMetadataItemPathKey, NSMetadataItemPixelWidthKey, NSMetadataItemPixelHeightKey}
-- build query and run it
set thePred to current application's NSPredicate's predicateWithFormat:"kMDItemContentTypeTree CONTAINS 'public.image'"
set theQuery to current application's NSMetadataQuery's new()
theQuery's setPredicate:thePred
theQuery's setSearchScopes:{theURL}
theQuery's startQuery()
repeat while theQuery's isGathering() as boolean
delay 0.01
end repeat
theQuery's stopQuery()
-- loop through results
set theCount to theQuery's resultCount()
repeat with i from 1 to theCount
set aResult to (theQuery's resultAtIndex:(i - 1))
-- get the values we're interested in
set theValues to (aResult's valuesForAttributes:requiredKeys)
set theWidth to (theValues's objectForKey:NSMetadataItemPixelWidthKey)
if theWidth is not missing value then -- ignore files with no pixel value; they're not bitmap format
set thePath to (theValues's objectForKey:NSMetadataItemPathKey)
-- check the file is directly in the folder, and not a subfolder
if (thePath's stringByDeletingLastPathComponent()'s isEqualToString:folderPath) as boolean then
if theWidth as real < 1500 or (theValues's objectForKey:NSMetadataItemPixelHeightKey) as real < 1500 then
-- if we get here, we need to change the label
set thisURL to (current application's |NSURL|'s fileURLWithPath:thePath)
(thisURL's setResourceValue:6 forKey:NSURLLabelNumberKey |error|:(missing value))
end if
end if
end if
end repeat
No, I wrote it that way very deliberately to make it less confusing to a neophyte user.
I use relative-aliases for everything on my own system (unless I have a good reason to do otherwise), but I find that other users (especially new ones) are confused by them.
No offense but your “construct” is much much much more confusing “ and more coercion-expensive “ than using the built-in relative paths
For example:
Your syntax:
[format]“~/Pictures/jpgs” → POSIX path
disk item imageFolderPath → System Events specifier (expands tilde)
POSIX path of → POSIX path
POSIX file → file URL
as alias → alias
as text → HFS path[/format]
Built-in relative paths syntax:
[format](path to pictures folder as text) & “jpgs”[/format]
My script rewritten pretty much the way I’d use it at home.
Shane’s suggestions are incorporated.
Added is a test for ˜public.image’
I switched from sed to Perl, so I could more easily deal with the kMDItemContentTypeTree tree.
Choose Folder is the default, although there’re lines demonstrating the use of a relative-alias and the Finder’s insertion location.
-------------------------------------------------------------------------------------------
# User Settings:
-------------------------------------------------------------------------------------------
set labelIndex to 6
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
--» Choose Folder or Relative-Alias or Finder Insertion Location ” take your pick.
-------------------------------------------------------------------------------------------
set imageFolderAlias to choose folder
-------------------------------------------------------------------------------------------
# set imageFolderAlias to alias ((path to home folder as text) & "test_directory:Image_Test_Folder:")
-------------------------------------------------------------------------------------------
# tell application "Finder" to set imageFolderAlias to insertion location as alias
-------------------------------------------------------------------------------------------
set imageFolderPath to POSIX path of imageFolderAlias
set imageFolderHFS to imageFolderAlias as text
set shCMD to "
cd " & quoted form of imageFolderPath & ";
mdls -raw -name kMDItemContentTypeTree -name kMDItemFSName -name kMDItemPixelWidth -name kMDItemPixelHeight * \\
| perl -0777 -ne '
s!\\x{00}!\\n!g;
s!^[()]\\n?!!mg;
s!^[[:blank:]]*|\"$!!mg;
s!^\"!!mg;
s!\"(,)\\n!$1 !mg;
print;
'"
set dataList to paragraphs of (do shell script shCMD)
tell application "Finder"
repeat with i from 1 to (length of dataList) by 4
set {fileTypes, fileName, pixelHeight, pixelWidth} to (items i thru (i + 3) of dataList)
if (fileTypes contains "public.image") then
if (pixelHeight as integer < 1500) or (pixelWidth as integer < 1500) or (pixelHeight = "(null)") or (pixelWidth = "(null)") then
set theFile to (imageFolderHFS & fileName) as alias
set label index of theFile to labelIndex
end if
end if
end repeat
update alias imageFolderHFS
end tell
-------------------------------------------------------------------------------------------
I don’t like fooling around with file dialogs and try to avoid them, so when possible I usually use insertion location in the Finder to operate on the front Finder window.
The script runs in about 5 seconds on a closed folder containing 650 files (on my system) “ with the folder open it takes about 8 seconds.
Operating on 100 files in the front Finder window takes ~1.2 seconds.
I reckon Shane’s script will be a bit faster “ especially as the number of files goes up.