Does this folder contain image files?

How can I check a folder to see if it contains image files.
Currently I can loop through the files in the folder and compare the extensions to a list of extensions and beep if the extension matches, but can I set a variable to true and exit the loop if a match is found? There must be a better way.


set image_types to {"jpg", "jpeg", "png", "tiff", "tif", "gif", "bmp"}
tell application "Finder"
	repeat with eachFile from 1 to number of files in folder (imagesDir as alias)
		set theFile to item eachFile in imagesDir as alias
		if the name extension of theFile is in image_types then
			beep
		end if
	end repeat
end tell

The finder will beep for every file that matches in the folder.
I want to break out of the loop and do further processing (not on the image files) if a match is found, and different processing if a match isn’t found.

Actually you don’t need a loop, the whose clause can filter the files.

The result of the script is the variable folderContainsImages which is true or false

set image_types to {"jpg", "jpeg", "png", "tiff", "tif", "gif", "bmp"}

set imagesDir to choose folder
tell application "Finder" to set numberOfImageFiles to (count (get files of imagesDir whose name extension is in image_types))
set folderContainsImages to numberOfImageFiles > 0

As the Finder is quite slow this is an alternative using Spotlight search (mdfind). As mdfind displays results in all subfolders of the base folder the regular expression after egrep filters the files in the subfolders.

set imagesDir to quoted form of POSIX path of (choose folder)
set numberOfImageFiles to count paragraphs of (do shell script "mdfind -onlyin " & imagesDir & " 'kMDItemContentTypeTree  = \"public.image\"' | egrep  '^" & imagesDir & "[^/]+$'")
set folderContainsImages to numberOfImageFiles > 0

When I run the mdfind version and choose this path:

I get this error:

Which surprises me since you are using “quoted form of.” I haven’t looked into it yet.

Ah, yes.
I knew there should be a better way to do this.

Thanks!

A try loop will catch the error if there are no images.


set imagesDir to quoted form of POSIX path of (choose folder)
try
	set numberOfImageFiles to count paragraphs of (do shell script "mdfind -onlyin " & imagesDir & " 'kMDItemContentTypeTree  = \"public.image\"' | egrep  '^" & imagesDir & "[^/]+$'")
	set folderContainsImages to numberOfImageFiles > 0
on error
	set folderContainsImages to 0
end try
if folderContainsImages is true then
	display dialog "Do stuff if there are images"
else
	display dialog "No images, Just continue with the rest of the script"
end if

Sorry, the mdfind script doesn’t consider the case that the folder doesn’t contain any files

Here you go

set folderContainsImages to false
set imagesDir to quoted form of POSIX path of (choose folder)
try
	set numberOfImageFiles to count paragraphs of (do shell script "mdfind -onlyin " & imagesDir & " 'kMDItemContentTypeTree = \"public.image\"' | egrep '^" & imagesDir & "[^/]+$'")
	set folderContainsImages to numberOfImageFiles > 0
end try

The folder in question has 109 .jpg’s, 62 png’s, 8 tiff’s, etc.

Stefan,

Your scripts fail here when there are spaces in the path. I think the problem is that you need quoted form for the path in the mdfind, but not in the egrep:

do shell script "mdfind -onlyin " & quoted form of imagesDir & " 'kMDItemContentTypeTree = \"public.image\"' | egrep '^" & imagesDir & "[^/]+$'"

It also relies on the POSIX path having a trailing /, which could be a trap.

But as you mentioned speed :), let me suggest a couple of alternatives. First, using my Metadata Lib instead of mdfind, and an ASObjC predicate to filter the results. This is more than twice as fast as the shell method in my (admittedly simple) tests:

use scripting additions
use framework "Foundation"
use mdLib : script "Metadata Lib" version "1.0.0"

set theFolder to POSIX path of (choose folder)

set theList to mdLib's searchFolders:{theFolder} searchString:"kMDItemContentTypeTree = 'public.image'" searchArgs:{}
set theList to current application's NSArray's arrayWithArray:theList
set thePred to current application's NSPredicate's predicateWithFormat:"stringByDeletingLastPathComponent IN %@" argumentArray:{{theFolder, text 1 thru -2 of theFolder}}
(theList's filteredArrayUsingPredicate:thePred) as list

But really, I don’t see the point in using Spotlight data for non-recursive stuff. Here’s an ASObjC version that uses the file manager instead:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set theFolder to "/Users/shane/Desktop/"
set theURL to current application's |NSURL|'s fileURLWithPath:theFolder
set {theFiles, theError} to current application's NSFileManager's defaultManager()'s contentsOfDirectoryAtURL:theURL includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(reference)
set thePred to current application's NSPredicate's predicateWithFormat:"pathExtension IN[c] %@" argumentArray:{{"jpg", "jpeg", "png", "tiff", "tif", "gif", "bmp"}}
set theFiles to (theFiles's filteredArrayUsingPredicate:thePred)'s valueForKey:"path"

No need to worry about whether the Spotlight index is up to date – and it runs more than 10x faster than the shell approach.

AppleScript Toolbox can search the spotlight database as well:

AST query metadata "kMDItemContentTypeTree = public.image" only in folders imagesDir

Parameter only in folders can either be an path or an list of paths, therefore the plural form.

Or as shane mentioned for non-recursive you can also use the file manager.

AST list folder imagesDir matching regex "\\.(jpg|jpeg|png|tiff|tif|gif|bmp)$"