A script to find a file with a unique name

Hello Stefan

I re-made tests with :

set folderToSearch to POSIX path of ((path to documents folder as text) & "Test 2:")
set dogStr to "2014-06-17T21.27.45 sysPref Dock.png"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & " name:" & dogStr
do shell script cmdStr
log result (**)
set cmdStr to "mdfind -onlyin " & folderToSearch & " name:" & dogStr
do shell script cmdStr
log result (**)
tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell
set dogStr to "Excel"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & " name:" & dogStr
do shell script cmdStr
log result (*/Users/userName/Documents/Test/excel*)
set cmdStr to "mdfind -onlyin " & folderToSearch & " name:" & dogStr
do shell script cmdStr
log result (**)
tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell

set folderToSearch to POSIX path of ((path to documents folder as text) & "Test:")
set dogStr to "2014-06-17T21.27.45sysPrefDock.png"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & " name:" & dogStr
do shell script cmdStr
log result (**)
set cmdStr to "mdfind -onlyin " & folderToSearch & " name:" & dogStr
do shell script cmdStr
log result (**)
tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell
set dogStr to "Excel"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & " name:" & dogStr
do shell script cmdStr
log result (*/Users/userName/Documents/Test/excel*)
set cmdStr to "mdfind -onlyin " & folderToSearch & " name:" & dogStr
do shell script cmdStr
log result (*/Users/userName/Documents/Test/excel*)
tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell

It seems that this morning my eyes weren’t wide open.
When the folder path contain a space,
no instruction find the really existing file whose name is “2014-06-17T21.27.45 sysPref Dock.png”
the one using quoted form find the file named Excel
the one using the non-quoted path missed the file named Excel

When the folder path doesn’t contain a space,
no instruction find the really existing file whose name is “2014-06-17T21.27.45sysPrefDock.png”
Yes, I deliberately created a file whose spaces were removed in the filename.
the one using quoted form find the file named Excel
the one using the non-quoted path find the file named Excel

Why are the instructions unable to find the “long” filenames ?

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) samedi 2 avril 2016 15:26:30

We are still in the shell environment, so ALL parameters containing space characters must be escaped or quoted

set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)

Thanks

Before asking I used quoted form but only upon the filename without including name:

Here is what I get, and I’m puzzled.

set folderToSearch to POSIX path of ((path to documents folder as text) & "Test 2:")
set dogStr to "2014-06-17T21.27.45 sysPref Dock.png"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr # DON'T FIND ! WHY ?
log result (**)
set cmdStr to "mdfind -onlyin " & folderToSearch & " name:" & dogStr
do shell script cmdStr # Logically, DON'T FIND !
log result (**)
tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell
set dogStr to "Excel"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr # Find
log result (*/Users/userName/Documents/Test/excel*)
set cmdStr to "mdfind -onlyin " & folderToSearch & " name:" & dogStr
do shell script cmdStr # Logically, DON'T FIND !
log result (**)
tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell

set folderToSearch to POSIX path of ((path to documents folder as text) & "Test:")
set dogStr to "2014-06-17T21.27.45sysPrefDock.png"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr # DON'T FIND ! WHY ?
log result (**)
set cmdStr to "mdfind -onlyin " & folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr # Logically, DON'T FIND !
log result (**)
tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell
set dogStr to "Excel"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr # Find !
log result (*/Users/userName/Documents/Test/excel*)
set cmdStr to "mdfind -onlyin " & folderToSearch & " name:" & dogStr
do shell script cmdStr # Find !
log result (*/Users/userName/Documents/Test/excel*)
tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) samedi 2 avril 2016 17:38:11

Thanks for the feedback/suggestion to use “quoted form of”.

The solution is

  1. If the path contains a “~”, expand it to full POSIX path
  2. Use “quoted form of” in both the folderToSearch and the file name (dogStr)

After some extensive testing in Terminal using mdfind, I have learned this:

  1. If you want to use a path that has spaces, you must either (but not both):
    • Put the path in single quotes (aka quoted form of)
    • Escape the spaces with "" (in AS would be “\”)

I tested the following. “YES” means it worked. “NO” means it did NOT work.


### Ver 2 -- Moved expand path code to handler ###

set folderToSearch to expandPath("~/Documents/Test/SubFolder 1")
set fileName to "plain text file.txt" -- CAN BE PARTIAL FILE NAME

set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & "name:" & quoted form of fileName
set findResults to do shell script cmdStr

on expandPath(pPathStr)
	-- RETURNS full POSIX path
	
	local fullPath
	set fullPath to pPathStr
	
	if fullPath = "~" then
		set fullPath to (POSIX path of (path to home folder))
	else if fullPath starts with "~/" then
		set fullPath to (POSIX path of (path to home folder)) & text 3 thru -1 of fullPath
	end if
	
	return fullPath
end expandPath

I understood what Stefan wrote. Alas, as you may see in my late message, I face some cases where:
(1) I don’t use tilde path
(2) I apply quoted form to both pathname and couple ("name: & dogStr)
the searched file is not found although it really exists.

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) dimanche 3 avril 2016 11:22:17

That’s the problem. The quoted form should be applied ONLY to the filename (dogStr), NOT to the combined string of “name:filename”.

When I applied quoted form to ONLY the filename, it worked perfectly.

Nada.

try with :
set dogStr to “2014-06-17T21.27.45 sysPref Dock.png”

As you search for “Excel”, every syntax work but it’s wrong when we have “complicated” name to search.

set folderToSearch to POSIX path of ((path to documents folder as text) & "Test 2:")
set dogStr to "2014-06-17T21.27.45 sysPref Dock.png"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & "name:" & quoted form of (dogStr)
do shell script cmdStr # DON'T FIND ! WHY ?
log result (**)
set dogStr to "2014-06-17T21.27.45 sysPref Dock.png"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr # DON'T FIND ! WHY ?
log result (**)

tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell

set dogStr to "Excel A1"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & "name:" & quoted form of (dogStr)
do shell script cmdStr
log result
(*/Users/username/Documents/Test 2/excel.A1
/Users/username/Documents/Test 2/excel-A1
/Users/username/Documents/Test 2/excel A1*)
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr
log result
(*/Users/username/Documents/Test 2/excel.A1
/Users/username/Documents/Test 2/excel-A1
/Users/username/Documents/Test 2/excel A1*)


tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell


set folderToSearch to POSIX path of ((path to documents folder as text) & "Test:")
set dogStr to "2014-06-17T21.27.45sysPrefDock.png"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr # DON'T FIND ! WHY ?
log result (**)
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & "name:" & quoted form of (dogStr)
do shell script cmdStr # DON'T FIND ! WHY ?
log result (**)

tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell

set dogStr to "Excel.A1"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr
log result (*/Users/username/Documents/Test/excel.A1*)
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & quoted form of ("name:" & dogStr)
do shell script cmdStr
log result (*/Users/username/Documents/Test/excel.A1*)

tell application "System Events"
	exists file (folderToSearch & dogStr)
	log result (*true*)
end tell

The two folders contain:
“2014-06-17T21.27.45 sysPref Dock.png”
“2014-06-17T21.27.45sysPrefDock.png”
“Excel”
“Excel A1”
“Excel-A1”
“Excel.A1”

As you see, a space in dogStr apply as a wildcard allowing the found character to be space, “-”, “.”

The behavior reported with “complicated” names isn’t specific to my machine, Stefan tested it and got the same “puzzling” one.

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) lundi 4 avril 2016 09:55:07

Very happy to see that my dog variable has become embedded in the code: it is likely to be my only contribution!:smiley:

That works fine for me in Yosemite 10.10.5:


set folderToSearch to expandPath("~/Documents/Test")
set fileName to "2014-06-17T21.27.45 sysPref Dock.png" -- CAN BE PARTIAL FILE NAME

set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & "name:" & quoted form of fileName
set findResults to do shell script cmdStr

on expandPath(pPathStr)
	-- RETURNS full POSIX path
	
	local fullPath
	set fullPath to pPathStr
	
	if fullPath = "~" then
		set fullPath to (POSIX path of (path to home folder))
	else if fullPath starts with "~/" then
		set fullPath to (POSIX path of (path to home folder)) & text 3 thru -1 of fullPath
	end if
	
	return fullPath
end expandPath

RETURNS:

Thanks for the feedback.
It gives an interesting info : the problem strikes only on 10.11.x

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) mardi 5 avril 2016 10:48:27

While this script works very well in most cases it fails if the file name contains certain characters, such as

These are the ones i have discovered so far.
Is there a way around this - other people’s files sent to me, for instance, wont have been named with these limitations in mind.
If there is no way around it then i presume it is something to do with file naming conventions. If so where can I find a list of characters that cannot be used in filenames in this context?

I’m not sure than colon is welcome in a filename because it’s the level separator in HFS paths.
In fact, when I try to insert a colon in a filename, the Finder issue an error message.

Looking in mdfind man I saw that * is supposed to be a wildcard but when I tried to use it, it failed.
At least under 10.11, a space char may be used as a wildcard replacing the characters -, >, <, *, ., |, ., ?, ^, ~, !, %, +, * and probably some other ones.

Using this feature give me the ability to find files named as “2014-06-17T21.27.45 sysPref Dock.png”

At last I found a track of explanation. The dash is a wrongdoer when it’s enclosed by digits as it may be deciphered as a substraction operator. It’s just a track because the characters + or * haven’t this annoying behavior.

In mdfind man I found the option -literal described with : Force the provided query string to be taken as a literal query string, without interpretation.
I hoped that it would get rid of the dash behavior but it doesn’t.

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) mercredi 6 avril 2016 10:00:38

Depends on file system you’re using. Finder behaves, for backward compatibility, as if the file names are HFS. For better compatibility with the transition from Mac OS to Mac OS X Cocoa save dialog for instance behaves like this too. But in fact when typing a slash in the save dialog, a filename with a colon is created in UFS. Using a colon in mdfind is perfectly fine because you’re using UFS, the colon is only presented as an “/” in Finder".

Update:
Here an example:

do shell script "mdfind 'kMDItemFSName = Apache::*'"

And with AppleScript Toolbox:

AST query metadata "kMDItemFSName = Apache::*"

Thanks for the precision.
In your sample code I saw that you use * as a wildcard.
I tested it and it works while it didn’t when I tried to use it in :

set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & space & “name:” & quoted form of fileName
set findResults to do shell script cmdStr

In fact it seems that this wildcard must be at the beginning or at the end of the searched string. If it is in the middle, it’s treated as a standard character.

If the space character may behave as a wildcard when we use the option name:, it doesn’t when I use kMDItemFSName.
As

do shell script "mdfind 'kMDItemFSName = 2014-06-17T21.27.45 sysPref Dock.*'"

returned nothing, (exactly as

do shell script "mdfind 'kMDItemFSName = 2014-06-17T21.27.45 sysPref Dock.png'"

, I tried

do shell script "mdfind 'kMDItemFSName = 2014 06 17T21.27.45 sysPref Dock.*'"

but it returned only files whose name is 2014 which is definitely not what I wanted.
So I must continue to use mdfind with name: using the space as wildcard.

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) mercredi 6 avril 2016 16:18:55

And if you try?

do shell script "mdfind 'kMDItemFSName = \"2014 06 17T21.27.45 sysPref Dock.*\"'"

I should have done it in my example in the previous post.

THANKS !

set folderToSearch to POSIX path of ((path to documents folder as text) & "Test")

set shortName to "2014-06-17T21.27.45 sysPref Dock."
set fileName to shortName & "png"

set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch & " kMDItemFSName = " & quoted form of (quote & shortName & "*" & quote)
set findResults to do shell script cmdStr
log result (*/Users/userName/Documents/Test/2014-06-17T21.27.45 sysPref Dock.png*)


set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch &  " name:" & quoted form of (quote & fileName & quote)
set findResults to do shell script cmdStr
log result (*/Users/userName/Documents/Test/2014-06-17T21.27.45 sysPref Dock.png*)


set fileName to "Excel"
set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch &  " name:" & quoted form of (quote & fileName & quote)
set findResults to do shell script cmdStr
log result (*/Users/userName/Documents/Test/excel.A1
/Users/userName/Documents/Test/excel-A1
/Users/userName/Documents/Test/excel A1
/Users/userName/Documents/Test/excel A
/Users/userName/Documents/Test/excel*)

Quoting " kMDItemFSName = " or " name:" was useless so I made a bit of cleaning.

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) mercredi 6 avril 2016 19:07:50

Thanks Yvan for your perseverance on this issue. :slight_smile:

So, let me make sure I understand the key change that make the mdfind work for you.

Before, I had:


. . . &  " name:" & quoted form of fileName

Your change is to put the fileName in quotes:


. . . &  " name:" & quoted form of (quote & fileName & quote)

Did I get that right?

Exactly. According to DJ Bazzie Wazzie I enclosed the filename with quotes and of course I applied quoted form.
With these extra steps, I was able to retrieve the file which I missed before.
Of course, it’s not required for names without “special” characters but it don’t hurt.
set dogStr to “Excel”
quoted form of (quote & dogStr & quote)
behaves well so In my library of handler I will store the code which works with every strings.

As I am curious I made other tests. It seems that the character which create difficulties is the dash (-)
I assumed that it’s because the sequence “2014-06-17” may be interpreted as an arithmetic operation but there is no problem with “2014-06+17” or “2014+06+17”
With “2014+06-07” the quotes are required.

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) vendredi 8 avril 2016 10:06:17

Recap

I’d like to give my sincere thanks to all that were involved with and contributed to this thread.
I have learned much thanks to you guys.

It seems that now we have a consensus on a solid solution that should work with all file names and with both Yosemite and El Capitan. So, I’d like to post a script that refactors the solution into a handler that hopefully can be used by all.

It has two test cases built into the script, but I have tested only on Yosemite 10.10.5.
Please add to this if you have other test cases and/or El Capitan.

Of course, I don’t have to say please review, test, and comment, because that is what you guys do best!

Submitted for your review, comment, and revision:


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#     Purpose:     Test mdFind Handler		
#-------------------------------------------------------------------------------------
#     Ver 1.0   2016-04-09
#     REF:      http://macscripter.net/viewtopic.php?pid=185534#p185534
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

use AppleScript version "2.4"
use scripting additions
--use JMLib : script "JMichaelLibAS"

### TEST CASE 1 ###
-- make sure it handles subfolders with spaces
set fileList1 to mdFind("~/Documents/Test/SubFolder 1", "plain text file.txt")
log fileList1

### TEST CASE 2 ###
-- make sure it handles unusual file names
set fileList2 to (mdFind("~/Documents/Test", "2014-06-17T21.27.45 sysPref Dock.png"))
log fileList2

--~~~~~~~~~~~~~~~~~~~~~ END OF MAIN SCRIPT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

on mdFind(pFolderPathStr, pFileNameStr)
	(*
	VER: 	2.0		LAST UPDATE:   2016-04-09
	
	PURPOSE:
		¢ Get a List of Files (fullpath) found in a folder, and all sub-folders,
		  that match a full or partial file name
		  
	PARAMETERS:
		¢ pFolderPathStr	text	POSIX path (may use ~) to folder to start search in
		¢ pFileNameStr		text	Full or partial file name to search for
		
	RETURNS:
		¢ findResults		text	Zero or more file paths that meet criteria, one file per line
	
	AUTHORS:	The Team at Macscripter.net
				(in alphabetic order)
					¢ DJ Bazzle Wazzle
					¢ JMichaelTX
					¢ StefanK
					¢ Yvan Koenig
	
	REQUIRED:
		1.	Mac OS X Yosemite 10.10.5+
							
		4.	INTERNAL HANDLERS:
				¢ expandPath(pPathStr) -- expands POSIX path with ~ to full POSIX path
	
	METHOD:
		¢ USE OF BOTH QUOTED FORM OF AND QUOTE
		  as in:  quoted form of (quote & fileName & quote)
		  
				This is apparently needed with some file names that have unusual characters
				or combinations of characters.
			For details see:
			http://macscripter.net/viewtopic.php?pid=185534#p185534
	
	REF:  The following were used in some way in the writing of this script.
		1.	MacScripter.net Topic A script to find a file with a unique name
			http://macscripter.net/viewtopic.php?id=44776&p=1
	===============================================================================
	   
	*)
	
	local folderToSearch
	local findResults
	
	set findResults to ""
	set folderToSearch to expandPath(pFolderPathStr) -- of JMLib
	
	set cmdStr to "mdfind -onlyin " & quoted form of folderToSearch ¬
		& " name:" & quoted form of (quote & pFileNameStr & quote)
	
	set findResults to do shell script cmdStr -- CALL mdfind in SHELL SCRIPT
	
	return findResults
	###END~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
end mdFind

on expandPath(pPathStr)
	###BEGIN~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	#     Name:     expandPath(pPathStr)			
	#     Purpose:  Converts Path with ~ to Full POSIX Path
	#		RETURNS:  full POSIX path as text
	#-------------------------------------------------------------------------------------
	#     Ver 1.0   2016-04-02
	#     AUTHOR:   JMichaelTX
	###””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””
	
	local fullPath
	set fullPath to pPathStr
	
	if fullPath = "~" then
		set fullPath to (POSIX path of (path to home folder))
	else if fullPath starts with "~/" then
		set fullPath to (POSIX path of (path to home folder)) & text 3 thru -1 of fullPath
	end if
	
	return fullPath
	###END~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
end expandPath


RESULTS:

After upgrading to amp 16 this script has stopped working…
I get the error message:
“The command terminated due to receipt of a signal.” in a filmmaker dialog box and then
“The command terminated due to receipt of a signal.” also in a filmmaker dialog box…I then get Filemaker quit unexpectedly, however despite the error log window appearing, filmmaker does not actually quit.