AppleScript to prompt Spotlight to search in a specific folder?

Hello,

I would like to be able to quickly invoke Spotlight to search among the contents of a specific folder. Would it be easy for any of you to create an AppleScript that will:

  • Open a window with an input field for search terms and two buttons - Cancel and Search.
  • Upon click of “Search”, will instruct Spotlight to search using the terms but with this restriction: -onlyin “/Users/USER/Library/Application Support/VoodooPad/Spotlight Index/”

I plan to assign this script to a hotkey so I can easily execute searches.

Thank you!
Erik

Model: PowerBook G4
AppleScript: 2.1.1
Browser: Firefox 2.0.0.3
Operating System: Mac OS X (10.4)

HI Erik,

something like this, but how do you want the search results to be displayed?

display dialog "Enter search string" default answer "" buttons {"Cancel", "Search"} default button 2
set {text returned:t, button returned:b} to result
if b is "Search" then
	set d to quoted form of (POSIX path of ((path to home folder as Unicode text) & "Library:Application Support:VoodooPad:Spotlight Index:"))
end if
set found to paragraphs of (do shell script "mdfind -onlyin " & d & space & quoted form of t)

Thank you Stefan. I suppose that ideally the results would be displayed in a Spotlight window so I can just click on the appropriate result to open the appropriate page. Would that be hard to do?
Thank you,
Erik

Yes, I think so. I have no idea to “redirect” the result to a spotlight window

Hmmm. Would it be difficult to have the script display the resulting files (and only the resulting files) in a single Finder window? Then perhaps I could just double-click on the one I want to open.

Maybe this is sufficient for you

display dialog "Enter search string" default answer "" buttons {"Cancel", "Search"} default button 2
set {text returned:t, button returned:b} to result
if b is "Search" then
	set d to quoted form of (POSIX path of ((path to home folder as Unicode text) & "Library:Application Support:VoodooPad:Spotlight Index:"))
end if
set found to paragraphs of (do shell script "mdfind -onlyin " & d & space & quoted form of t)
set nameList to {}
set {TID, text item delimiters} to {text item delimiters, "/"}
repeat with i in found
	set end of nameList to last text item of contents of i
end repeat
set text item delimiters to TID
set FilesToOpen to choose from list nameList with multiple selections allowed
if result is false then return
set FilesToOpenList to {}
repeat with i in FilesToOpen
	repeat with j from 1 to (count nameList)
		if contents of i is item j of nameList then
			set end of FilesToOpenList to item j of found
			exit repeat
		end if
	end repeat
end repeat
repeat with i in FilesToOpenList
	set o to POSIX file i
	tell application "Finder" to open o
end repeat

Well here is what I came up with. simple, but it works

set {text returned:t, button returned:b} to (display dialog "Enter search string" default answer "" buttons {"Cancel", "Search"} default button 2)
set d to quoted form of (POSIX path of ((path to home folder as Unicode text) & "Library:Application Support:VoodooPad:Spotlight Index:"))
try
	tell application "Finder" to open (item 1 of (choose from list (paragraphs of (do shell script "mdfind -onlyin " & d & space & quoted form of t))) as POSIX file)
end try

Of course in the mean time Mr. S came up with a more eloquent and robust example.

I noticed that both does last script, throw up a empty result dialog if no results are found.
Hope you do not mind …
mad an edit, so it will ask’s you if you want to search again if no results are found

set rezult to ""
global rezult
my find_it()
on find_it()
	set {text returned:t, button returned:b} to (display dialog "Enter search string" default answer "" buttons {"Cancel", "Search"} default button 2)
	set d to quoted form of (POSIX path of ((path to home folder as Unicode text) & "Library:Application Support:VoodooPad:Spotlight Index:"))
	try
		tell application "Finder" to set rezult to (do shell script "mdfind -onlyin " & d & space & quoted form of t)
	end try
	if rezult is not "" then
		tell application "Finder" to open (item 1 of (choose from list (paragraphs of rezult)) as POSIX file)
	else
		display dialog " No Items found " buttons {"Cancel", "Search Again"} default button 2
		if the button returned of the result is "Search Again" then
			my find_it()
		end if
	end if
end find_it

Thank you all!

Stefan’s script currently seems the best for me because it just displays the filename without the path. However, each filename ends in “.vpspotlight” and the redundancy and length of that obscures the results. Is there any way to eliminate the filename extension?

One other question: how are the results sorted? By some sort of % match? If I wanted to (although I’m not sure if I do), could I change something so the sorting is alphabetical?

All the best,
Erik

You’re pretty challenging. :wink:

There is no sorting, the order of mdfind is the “order of appearance”
A sorting routine is possible also to strip the name extension,
but it rather slows down the script.


set t to text returned of (display dialog "Enter search string" default answer "" buttons {"Cancel", "Search"} default button 2)
set d to quoted form of (POSIX path of ((path to home folder as Unicode text) & "Library:Application Support:VoodooPad:Spotlight Index:"))
set found to paragraphs of (do shell script "mdfind -onlyin " & d & space & quoted form of t)
if found is {""} then display dialog "No matches found" buttons {"Cancel"} default button 1
set nameList to {}
repeat with i in found
	set {name:Nm, name extension:Ex} to info for POSIX file i as alias
	if Ex is missing value then set Ex to ""
	if Ex is not "" then set Nm to text 1 thru ((count Nm) - (count Ex) - 1) of Nm
	set end of nameList to Nm
end repeat
sort_items(nameList, found)
set FilesToOpen to choose from list nameList with multiple selections allowed
if result is false then return
set FilesToOpenList to {}
repeat with i in FilesToOpen
	repeat with j from 1 to (count nameList)
		if contents of i is item j of nameList then
			set end of FilesToOpenList to item j of found
			exit repeat
		end if
	end repeat
end repeat
repeat with i in FilesToOpenList
	set o to POSIX file i
	tell application "Finder" to open o
end repeat

to sort_items(sortList, SecondList)
	script l
		property srt : sortList
		property sec : SecondList
	end script
	tell (count l's srt) to repeat with i from (it - 1) to 1 by -1
		set s to (l's srt)'s item i
		set r to (l's sec)'s item i
		
		repeat with i from (i + 1) to it
			tell (l's srt)'s item i to if s > it then
				set (l's srt)'s item (i - 1) to it
				set (l's sec)'s item (i - 1) to (l's sec)'s item i
			else
				set (l's srt)'s item (i - 1) to s
				set (l's sec)'s item (i - 1) to r
				exit repeat
			end if
		end repeat
		if it is i and s > (l's srt)'s end then
			set (l's srt)'s item it to s
			set (l's sec)'s item it to r
		end if
	end repeat
end sort_items
 

Awesome, thank you Stefan. The speed hit is unfortunate, but the script works great otherwise.

I know I asked for a lot and I appreciated your help! The next script question I’m going to post is likely way too challenging for folks to volunteer their expertise on. :frowning:

BTW - I just made a small donation to MacScripter on behalf of StefanK, James Nierodzik, Mark Hunte as a token of appreciation.

All the best,
Erik

Oops - one more question about this script: when I use iKey to call the script the cursor does not appear in the search term input box. Is there any way to make the cursor move there automatically so I don’t have to take additional steps to select the input box before I start typing in my search terms?
Thank you,
Erik

This might be a problem of iKey,
the script works when started directly

Okay, thank you Stephan. I’ll look into it in iKey.
Erik

Very cool script… is there any chance you could comment the following?

	repeat with i in found
		set {name:Nm, name extension:Ex} to info for POSIX file i as alias
		if Ex is missing value then set Ex to ""
		if Ex is not "" then set Nm to text 1 thru ((count Nm) - (count Ex) - 1) of Nm
		set end of nameList to Nm
	end repeat

I’d actually like to modify this so the name includes the parent directory, and I’m not quite
understanding what exactly is happening in the above.

the code strips the name from the whole name with name extension


-- found is s list of POSIX paths
repeat with i in found
	-- gets name und name extension of the list item i (e.g. Nm:"foo.pdf", Ex:"pdf")
	set {name:Nm, name extension:Ex} to info for POSIX file i as alias
	-- if there is no name extension (indicated as missing value), set it to an empty string
	if Ex is missing value then set Ex to ""
	-- strip the name from the name extension (e.g. Nm:"foo", Ex:"pdf")
	if Ex is not "" then set Nm to text 1 thru ((count Nm) - (count Ex) - 1) of Nm
	-- add the name to the list nameList
	set end of nameList to Nm
end repeat

thank you.