Search for file in folders and subfolders

Hello Shane.
Is what I get the normal behavior ?

use scripting additions
use framework "Foundation"

(current application's NSDirectoryEnumerationSkipsPackageDescendants)
--> 2

(current application's NSDirectoryEnumerationSkipsSubdirectoryDescendants)
--> 1

(current application's NSDirectoryEnumerationSkipsPackageDescendants) + (get current application's NSDirectoryEnumerationSkipsSubdirectoryDescendants)
--> 3
(current application's NSDirectoryEnumerationSkipsPackageDescendants) + (current application's NSDirectoryEnumerationSkipsSubdirectoryDescendants)
--> error "Impossible de convertir NSDirectoryEnumerationSkipsSubdirectoryDescendants en type number." number -1700 from NSDirectoryEnumerationSkipsSubdirectoryDescendants to number

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 26 février 2021 16:43:43

Yvan,

Your example probably clarifies something. As far as I know, parentheses should implicitly mean getting the value of an object instead of a reference to an object. The fact that this is not happening really looks like a bug:


use scripting additions
use framework "Foundation"

(get current application's NSDirectoryEnumerationSkipsPackageDescendants) + (get current application's NSDirectoryEnumerationSkipsSubdirectoryDescendants) + (get current application's NSDirectoryEnumerationSkipsHiddenFiles)
--> 7
(current application's NSDirectoryEnumerationSkipsPackageDescendants) + (current application's NSDirectoryEnumerationSkipsSubdirectoryDescendants) + (current application's NSDirectoryEnumerationSkipsHiddenFiles)
--> Error: "Can’t make NSDirectoryEnumerationSkipsSubdirectoryDescendants into type number."

In your code, the very first get is useless.
My understanding is that we are facing a code which doesn’t achieve all what we assume it must do.

If my memory is OK, there is something related to reference but I don’t know the exact English word.

use scripting additions
use framework "Foundation"

-- Here, no need for parentheses
current application's NSDirectoryEnumerationSkipsPackageDescendants --> 2

set v1 to current application's NSDirectoryEnumerationSkipsSubdirectoryDescendants --> 1

-- Below parentheses are required
(current application's NSDirectoryEnumerationSkipsPackageDescendants) + (get current application's NSDirectoryEnumerationSkipsSubdirectoryDescendants)
--> 3

(current application's NSDirectoryEnumerationSkipsPackageDescendants) + v1 --> 3

try
	v1 + (current application's NSDirectoryEnumerationSkipsPackageDescendants)
on error errMsg
	log errMsg --> error "Impossible de convertir NSDirectoryEnumerationSkipsPackageDescendants en type number." number -1700 from NSDirectoryEnumerationSkipsPackageDescendants to number
end try

try
	(current application's NSDirectoryEnumerationSkipsPackageDescendants) + (current application's NSDirectoryEnumerationSkipsSubdirectoryDescendants)
on error errMsg
	log errMsg --> error "Impossible de convertir NSDirectoryEnumerationSkipsSubdirectoryDescendants en type number." number -1700 from NSDirectoryEnumerationSkipsSubdirectoryDescendants to number
end try

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 26 février 2021 18:24:52

Yes. The get resolves things.

Thank you Shane.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 27 février 2021 07:33:00

What makes you think this ?

I was confused by the fact that very often the expression with the get keyword has to be enclosed in parentheses.

Now I figured out what my confusion was: parentheses have to be used not in connection with get, but when the get keyword follows immediately after some other keyword. Here’s an example that wouldn’t work if I removed the parentheses (because “get” keyword follows “in” keyword) :

set URLs to {}
tell application "Finder"
	repeat with folder_ref in (get every folder of home)
		set end of URLs to URL of folder_ref
	end repeat
end tell

Here, as I understand, get keyword works as Finder command and not as AppleScript command. But my confusion above led to resolving the AsObjC issue (by Yvan Koenig). That is good :smiley:

Hi,

the following script of Peavine helped a lot but I’d like to ask a question for better understanding:
At the end of the script (see below) there ist a line:

if (count theFiles) = 0 then display dialog "A location file was not found for company " & theCompanyPrefix buttons {"OK"} cancel button 1 default button 1 with icon stop
	return ((theFiles's URLByDeletingLastPathComponent) as alias)

It displays an error message if no flag file was found.
Question: What does the ‘return’ command do?

As far as I understand ‘getFile’ is some kind of subroutine or handler that searches for the flag file.
If it finds the flag file, it returns the path and helps the main routine define the targetFolder.
So what exactly happens instead, if the flag file was not found?

I’m asking because I’d like to copy the sourceFile to another folder (for example called ‘orphans’) if no flag file was found. I tried to figure this out by myself by simply setting the targetFolder to an absolute path, but it didn’t work. If no file was found, everything simply stops.

Can anybody help?

Thanks again,
Carl

Carl. The AppleScript Language Guide succinctly answers your question as follows:

https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_handlers.html#//apple_ref/doc/uid/TP40000983-CH7g-163937

The following further illustrates what return does:

set returnedItem to testHandler() -- call handler and set returnedItem to "This is a test"

on testHandler()
	set someText to "This is a test" -- set variable
	return someText -- exit handler and return the contents of someText
	display dialog "This is a dialog" -- this line is never seen
end testHandler

In the code snippet you quote, if no files are found and the dialog is shown, an error number -128 is returned and the script is exited. In this instance, the return line does nothing. For example:

set returnedItem to testHandler() -- call handler but returnedItem is not set

on testHandler()
	display dialog "Some text" buttons {"OK"} cancel button 1 -- exits script
	return "This is a test" -- this line is never executed
end testHandler

Just as a final point, a return statement in the main body of a script exits the script.

Your understanding is correct–the script quits if the flag file is not found.

I’m not sure where you are with the script and if you’ve resolved the script’s copy-to-server issue discussed earlier in this thread. However, changing the code at the end of the handler to something like the following would appear to do what you want. I have used the desktop as the orphans folder just for simplicity sake, and I have omitted the dialog, which may be unnecessary. I ran a few tests and the script seems to work as desired. As noted before, I do not have a server for testing and put the target folder on an external drive instead.

use scripting additions
use framework "Foundation"

on main()
	set searchPath to "/Volumes/Store/Test/" -- this should be path to folder on server
	set sourceFiles to (choose file with multiple selections allowed)
	
	set ATID to AppleScript's text item delimiters
	repeat with aFile in sourceFiles
		set AppleScript's text item delimiters to {":"}
		set sourceFileName to text item -1 of (aFile as text)
		set AppleScript's text item delimiters to {"-"}
		set theCompanyPrefix to text item 1 of sourceFileName
		set theCompanyName to text item 2 of sourceFileName
		set locationFileName to theCompanyName & "-here_i_am.txt"
		set targetFolder to getFiles(searchPath, locationFileName, theCompanyPrefix)
		tell application "Finder" to duplicate aFile to targetFolder with replacing
	end repeat
	set AppleScript's text item delimiters to ATID
end main

on getFiles(theFolder, theName, theCompanyPrefix)
	set theFolder to current application's |NSURL|'s fileURLWithPath:theFolder
	set fileManager to current application's NSFileManager's defaultManager()
	set folderContents to (fileManager's enumeratorAtURL:theFolder includingPropertiesForKeys:{} options:((current application's NSDirectoryEnumerationSkipsPackageDescendants) + (current application's NSDirectoryEnumerationSkipsHiddenFiles as integer)) errorHandler:(missing value))'s allObjects()
	set thePred to current application's NSPredicate's predicateWithFormat_("(lastPathComponent ==[c] %@) AND (path MATCHES[c] %@)", theName, (".*?/" & theCompanyPrefix & ".*"))
	set theFiles to (folderContents's filteredArrayUsingPredicate:thePred)
	if (count theFiles) = 0 then
		return (path to desktop)
	else
		return ((theFiles's URLByDeletingLastPathComponent) as alias)
	end if
end getFiles

main()

Thank you peavine again, very much.

I implemented your suggestion into my script and it just works.
I love the simplicity and now I understand the ‘mechanics’ thanks to your kind explanation.