Return a list of Folders and Subfolders

Hi McUsr

Cannot thank you guys enough for all your help but I cannot get it to work correctly. I think it has something to do with spaces in the starting folder name. At Desktop I have the following folders

A New Test Folder
ApplescriptTest.
Test 2
sub2
Sub1
Test1
When I set the subject to “sub2” I get not found and this is what I get
tell application “AppleScript Editor”
choose folder
end tell
tell application “AppleScript Editor”
choose folder
→ alias “Macintosh HD:Users:mitch:Desktop:A New Test Folder:”
end tell
tell current application
do shell script "mdfind -onlyin /Users/mitch/Desktop/A New Test Folder/ ‘kMDItemFSName == "sub2" && ( kMDItemContentType == "public.folder" || kMDItemFSSize == 0 )’ "
→ error “Failed to create query for ‘New Test Folder/ kMDItemFSName == "sub2" && ( kMDItemContentType == "public.folder" || kMDItemFSSize == 0 )’.” number 1
end tell
tell application “AppleScript Editor”
display dialog “Not found”
→ {button returned:“OK”}
end tell
Result:
{button returned:“OK”}

I set up the folders from Applesxript Test in Desktop

ApplescriptTest.
Test 2
sub2
Sub1
Test1

and it works this is the result.
tell application “AppleScript Editor”
choose folder
end tell
tell current application
do shell script "mdfind -onlyin /Users/mitch/Desktop/ApplescriptTest/ ‘kMDItemFSName == "sub2" && ( kMDItemContentType == "public.folder" || kMDItemFSSize == 0 )’ "
end tell
tell application “System Events”
get POSIX path of container of disk item “/Users/mitch/Desktop/ApplescriptTest/Test 2/sub2”
get name of disk item “/Users/mitch/Desktop/ApplescriptTest/Test 2/sub2”
end tell
tell application “AppleScript Editor”
display dialog “Path to Folder:/Users/mitch/Desktop/ApplescriptTest/Test 2/sub2
Parent Folder of Folder /Users/mitch/Desktop/ApplescriptTest/Test 2
Name of Folder: sub2”
end tell
Result:
{button returned:“OK”}

I thought it may have been the number of levels “sub2” is 4 down from desktop in the failed example and only 3 down in the one that worked.
I then removed the spaces in the folder I started with and it works. It does not seem to matter if the subject has spaces just the starting point.

Having said that I tried looking for a file under “Documents” (no spaces) on my hard drive that did not work.

Sorry to ask again but can you help I guess I have to pad the name of the starting folder somehow.

thanks

Peter

Does not seem to like external drives either. I copied the exact file structure from Desktop to an external drive Same error.

tell current application
do shell script "mdfind -onlyin /Volumes/My Passport/ApplescriptTest/ ‘kMDItemFSName == "sub2" && ( kMDItemContentType == "public.folder" || kMDItemFSSize == 0 )’ "
→ error “Failed to create query for ‘Passport/ApplescriptTest/ kMDItemFSName == "sub2" && ( kMDItemContentType == "public.folder" || kMDItemFSSize == 0 )’.” number 1
end tell

Peter

Hello.

I have added the missing “quoted form of” in the example above. I recreated your folder structure, and tested it, it worked fine. I am sorry for the trouble, the spaces in filenames was something that slipped by me, when I wrote the example.

Hi McUsr

It appears that the problem with external drives is again a space. the name of the first one I tried it on “My Passport” when I went to one with out spaces it worked again.

You can see the difference “onlyin” the name of the volume “My Passport” but the failed query shows only “Passport”

do shell script "mdfind -onlyin /Volumes/My Passport/ApplescriptTest/ ‘kMDItemFSName == "sub2" && ( kMDItemContentType == "public.folder" || kMDItemFSSize == 0 )’ "
→ error “Failed to create query for 'Passport/ApplescriptTest/ kMDItemFSName == "sub2" && ( kMDItemContentType == "public.folder" || kMDItemFSSize == 0 )'.” number 1

Thanks

Peter

If you spell out folder names directly like that, then you need to put single quotes around them like this:

'/My passort drive/with lots a/ spaces/in its/directory names/'

when you are using such a path name in a variable, then you should apply qouted form.

Either “set myvar to quoted form of posix path of (the filename)”

Alternatively

set myvar to quoted form of myvar” (if the posix path is already acquired.)

I hope this helps. :slight_smile:

Hi McUsr

Had not see your last post have made that correction and it worked on the example thanks so much. It is amazingly quick.

I have three questions if you would not mind.

  1. The search term appears to be case sensitive can I change that even if it is an option for the user.
  2. I notice that the handler returns all the folders that start with the search term although tit is set to accept the first paragraph. Can I put a repeat loop in the handler so I can select the place I want?
  3. Can I make the search term specific again even as a user option?

I have a long way to go to get my eamils to use this ruotine but cannot thank you enough for your assistance.

Peter:)

Question 1
Nope, I think mdfind by itself is case sensitive, so that is a no no. if your search term consist of 5 letters, then we’d have 120 possible permutations. If you need case insensitivity dearly, then we’d have to generate a list by finder.

Question 2.

Haha, :slight_smile: I just posted a handler for those things: MacScripter / Easy to use yet versatile handler for finding folders by mdfind see if you can use that one! :slight_smile:

But you can use the handler in the post, with an empty search string, and it will return all folders, as long as the search predicate isn’t exact.

The handler will return a full list of folders if you set the result set to “every” or “all”

Question 3.
Yes, the handler a search predicate with “exact”, which only returns exact matches.

Hi McUsr

I have tried to combine your handler wit your previous suggestions but somehow I am not passing either the “resulttype” or “searchpredicate” correctly. I have forced them both to one of the options within the handler that works. when i use display dialog to see what they are at the handler they both appear to be correct. to make sure no spelling mistakes I copied the items from the handler to the “choose list”. Obviously doing something wrong. I have tried both as strings and text and that did not help.
If I set the searhpredicate within the handler I then get a problem with resulttype. If I set both it works so I think it is the way I am passing the data?

Here is the scrip as I have it

--This was developed with the help of  McUsr to return all the folders with a name of the search term. It is a start to be used as a way to file copies of incoming mail messages
set folderpath to quoted form of (POSIX path of (choose folder)) -- sets file path to folders selected 

display dialog "Enter Name of Folder(s) you are looking for" default answer "" --In a working application this will be provided either as subject or name sender recipient
set subject to text returned of result
--Added to allow for which entry is require  First,Last, All
set resultType to choose from list {"First", "Last", "All", "Every"} with prompt "Select Which Entry is required" as text
--Added to set up the degree of c=accuracy in the search term
set searchPredicate to choose from list {"contains", "begins with", "ends with", "exact"} with prompt "Determine Location of Search Name in String" as text

set objItem to my findFolderOnly(resultType, searchPredicate, subject, folderpath)
if objItem is not {} then
	
	tell application "System Events" to tell disk item objItem to set {resultType, searchPredicate, ParentFolder, Foldername} to {POSIX path of container of it, name of it}
	
	display dialog "Path to Folder:" & objItem & return & "Parent Folder of Folder " & ParentFolder & return & "Name of Folder: " & Foldername
else
	display dialog "Not found"
end if


on findFolderOnly(resultType, searchPredicate, searchterm, directoryToSearchIn)
	-- © 2012 McUsr and put into public domain, you may not post this on its own, nor make it available in a public repository.
	-- please refer to this link: http://macscripter.net/viewtopic.php?pid=156879#p156879
	--set directoryToSearchIn to quoted form of directoryToSearchIn
	display dialog "Search Predicate is " & searchPredicate & return & "Result type is " & resultType
	--set searchPredicate to "contains"
	if searchPredicate is "contains" then
		set searchterm to "\"*" & searchterm & "*\""
	else if searchPredicate is "begins with" then
		set searchterm to "\"" & searchterm & "*\""
	else if searchPredicate is "ends with" then
		set searchterm to "\"*" & searchterm & "\""
	else if searchPredicate is "exact" then
		set searchterm to "\"" & searchterm & "\""
	else
		error "The search predicate is misspelled!" number 4000
	end if
	if resultType = "first" or resultType = "last" or resultType = "all" or resultType = "every" then
		
		try
			local theResult
			set theResult to (do shell script "mdfind -onlyin " & directoryToSearchIn & " 'kMDItemFSName == " & searchterm & " && ( kMDItemContentType == \"public.folder\" || kMDItemFSSize == 0 )' ")
			if resultType = "first" then
				return first paragraph of theResult
			else if resultType = "last" then
				return last paragraph of theResult
			else if resultType = "every" or resultType = "all" then
				return theResult
			end if
		on error
			return {}
		end try
	else
		error "Wrong value for resulttype" number 4000
	end if
end findFolderOnly

thanks again

Peter :slight_smile:

Hello.

First of all, the choose from list, returns a list, so the searchPredicate, and the resultType parameters won’t get evaluated as text, and therefore fails.

Thanks for making me aware of this, I’ll enforce the handler with your findings. :slight_smile: In the mean time, use the handler like this:

set objItem to my findFolderOnly(resultType as text, searchPredicate as text, subject, folderpath)

The line that sets the parent folder, and folder name also needs to be fixed, to something like this:

tell application "System Events" to tell disk item objItem to set {ParentFolder, Foldername} to {POSIX path of container of it, name of it}

I see that you have changed the handler, it would be nice if you didn’t, or gave a notice when you did, as people may think that it is the original one, when it isn’t. (I think of the removal of “set quoted form of”, mainly, I understand the need for the display dialog for debugging purposes, (and so do others).

Hi McUsr

First my apologies for the change, other than the addition of display dialog(s) I commented out the quoted path as you had already told me to put that in the first script and I figured that any reader would see that as it had not been deleted. Anyway as I said I apologise and will make sure in future if I post the script again there is a reference to any change(s) I made.

Made your first change and it seems to work, have not run an extensive test yet as I wanted to get my apology underway. however your second change is as I thought you had it in the originally handler and is in the last scrip I sent to you,am I missing something.

As I have already made a mistake I would like ask if you are OK with me changing "directorytosearchin to folderpath. If you do not agree I will change the start of the routine so the variables that are being passed are the same names. I understand directory to be more of a UNIX term as opposed to folder in Applescript.

thanks again

Peter :frowning:

Oh my! I am sorry that you took it that way, I was just informing you.

Now, changing a parameter name, now that is not a big deal. Changing behaviour, that is something totally different. :slight_smile:

Never mind this, and proceed with your endeavours! :slight_smile:

Thank you it is important to me that given the time and effort you have put into helping me that I do not plagiarize your work or fail to acknowledge what you have done.

thanks again I am sure I will be back as I work through my project.

take care

Peter :frowning:

It is not about plagiarizing, it is really about knowing which version is which.

I am far more concerned about something I have written still works how I intended it to do.

Plagiarizing, now that would be if you stripped out the copyright notice, and said you had made it, maybe after changing the variable names, that is something entirely different.

Can’t we just drop this, and go on with something more productive? :smiley:

Absolutely

Hopefully you will help me with a new issue. As I think you know I am trying ultimately to selected a path based on the result of the search.

One thing I had to change was to allow a display of all the search results if I had called for a resulttype of “All” or Every" I did that by inserting an if then logic test.

if resultType as text = "All" or resultType as text = "Every" then
		display dialog "This is the list Returned from the handler " & MyFolderList
		set myActiveFolder to choose from list MyFolderList
	else
		tell application "System Events" to tell disk item objItem to set {ParentFolder, Foldername} to {POSIX path of container of it, name of it}
		display dialog "Path to Folder:" & objItem & return & "Parent Folder of Folder " & ParentFolder & return & "Name of Folder: " & Foldername
	end if

In my test case two folders met the criteria of an exact match and both were displayed from the “display dialog” command however the choose list only shows the first of the two. I think it may have something to do with delimiters but cannot figure out what.

Thanks

peter :slight_smile:

Hello.

When the handler are fed the “all” or “every” result type, then it returns a list.

You’d have to iterate over that list with something like this:


repeat with anObj in theResultList
	tell application "System Events" to tell disk item (contents of anObj) to set {ParentFolder, Foldername} to {POSIX path of container of it, name of it}
	display dialog "Path to Folder:" & objItem & return & "Parent Folder of Folder " & ParentFolder & return & "Name of Folder: " & Foldername
end repeat

# the contents of is included, as it doesn't harm, though I am not sure if it is totally needed either.

# as the "iterator-variable" just contains a reference into the list, and I am not sure how far
# Applescript will go into coercing this.

There are much faster approaches to this, than using this kind of construct, you could for instance use a handler like this to extract the information with.



set pxPath to POSIX path of (path to temporary items from user domain as text)
”> "/Users/mcusr/Library/Caches/TemporaryItems/"
set thPath to parentFol for pxPath
” > /Users/mcusr/Library/Caches/"

set folname to pxBasename for pxPath
”> "TemporaryItems"

to parentFol for aPxPath
		local tids, parFol
		set {tids, my text item delimiters} to {my text item delimiters, "/"}
		
		if (character (length of aPxPath) of aPxPath) = "/" then
			set parFol to text items 1 thru -3 of aPxPath as text
		else
			set parFol to text items 1 thru -2 of aPxPath as text
		end if
		set my text item delimiters to tids
		if parFol = "" then set parFol to "/"
		return parFol
	end parentFol

to pxBaseName for aPxPath
	local itm,tids
	if (text -1 of aPxPath = "/") then
		set itm to -2
	else
		set itm to -1
	end if
	set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "/"}
	set aPxPath to text item itm of aPxPath
	set AppleScript's text item delimiters to tids
	return aPxPath
end pxBaseName

Now, you could extract this info into a list, like I did with System Events, but it is no purpose of that now. (I did it with System Events to not generate to many Apple Events, as those are expensive, and choose to target the disk item, to give its properties in one go. :slight_smile:

Hi McUsr

I have tried the first suggestion and the problem is that the “repeat with anOBJ in MyFolderList” returns the entire list on the first iteration and then fails on (I assume the second) because it cannot get the disk item U/ and the list starts /Users/----. I need to break the list down to each entry which is why I asked about delimiters before. As each folderpath starts with/Users I was hoping to use that as a delimiter, but as I said have not figured how.

Thanks

Peter

Can you please just show an excerpt of the code.

I’d rally like to see your loop, and how you do it, before I can make an educated guess as to why your code fails.

On a general basis, please consult the AppleScript Language guide, that is either on the net at developer.apple.com, or as a part of the Developer installation from your CD, if you got them there, I also think you can get it all for free from the Appstore, Xcode, the documentation and everything.

The easiest is of course to just download it. :smiley:

I

Marc et al: I’ve very impressed with this whose clause. I’ve never seen anything like it, but would like to make use of this pattern.

However, it gets an error when I try this:


tell application "System Events"	
	set appNameList to every application process whose name is in my getList()
end tell

on getList()
	return {"Keyboard Maestro", "Finder", "Script Debugger"}
end getList

(* 
=== ERROR ===
System Events got an error: Can't make {"Keyboard Maestro", "Finder", "Script Debugger"} into type specifier.
*)

Any ideas/suggestions?

TIA.

Hello

My understanding is that you just need to insert a timeout.

This script behaved flawlessly :

with timeout of 36000 seconds
	tell application "Finder" to ((((path to desktop as text) & "pour ebay:") as alias)'s entire contents)'s folders whose name is in my getlist()
end timeout
on getlist()
	return {"_X28706Æ’YK", "_X28737Æ’YK", "_X28782Æ’YK", "_X28990Æ’YK", "_X29050Æ’YK", "_X29066Æ’YK", "_X29075Æ’YK", "_X29101Æ’YK", "_X29109Æ’"}
end getlist

Yvan KOENIG running Sierra 10.12.5 in French (VALLAURIS, France) lundi 5 juin 2017 10:32:25

Those are called filters and they are object specifiers. However, due to poor implementation they’re hard to manage and a lot of applications don’t support them. There is an KVC compatible way of coding to save yourself from writing many object accessor methods, but again there is no guarantee that the application supports it.

From what I can see is that the accessor method doesn’t support the is in operator but it does supports other operators like is. That means that when you use the is in operator the object cannot be resolved and therefore you get the type specifier error.