Open Folder with only partial pathnames.

Hello Macscripter,

I am usually a windows guy so I used a bashed together Applescript from here for the purpose of opening a Folder when given part of its pathname.

The old folder structure was composed out of a tree like this

Client
–ProjNum1_brochure
–ProjNum2_website

now the folder structure changed to one with subprojects (max depth needed is 2 Subfolders down the tree)

Client
–ProjNum1_brochure
–ProjNum123_spring_brochure
–ProjNum234_autumn_brochure
----ProjNum234_illustration_autumn (<-- this is the maximal depth needed for the script to work with)
–ProjNum2_website
–ProjNum345_spring_update
–ProjNum456_autumn_update

I used this script to open a folder when given a part of the pathname like “brochure” and it works fine for the old folder structure.

set projName to the text returned of 
  (display dialog "Projectnumber or name?" default answer "")
tell application "Finder"
set parentfolder to "Share:Client1" as alias
set subfolders to every folder in parentfolder whose name begins with "projName"
repeat with eachfolder in subfolders
open eachfolder
end repeat
end if
end tell

Is there an easy way (without using “entire contents”) to make the script work for a max depth of two subfolders?

best regards

nebukal

Sorry for the bad english.

Hi Yvan,

first thanks for your help. I tried it again the script just searches in subfolders if the projName given is in the Root say:

If there is a folder tree like this:

Client
–ProjNum1_brochure
–ProjNum123_spring_brochure
–ProjNum234_autumn_brochure
----ProjNum234_illustration_autumn (<-- this is the maximal depth needed for the script to work with)
–ProjNum2_website
–ProjNum345_spring_update
–ProjNum456_autumn_update

If I input say “brochure” into the dialog he opens every folder with “brochure” in its name down the tree but if I input autumn he doesn’t go deeper in the tree than “Client” and opens no folders.
Any help is appreciated … I am really kinda lost here.

EDIT OLD Information:
thanks for your help I changed your script a bit:

set projName to the text returned of (display dialog "Projectnumber or name?" default answer "")
tell application "Finder"
	set parentfolder to "Share:Client1" as alias
	set subfolders to every folder in parentfolder whose name contains projName
	if subfolders is not {} then
		repeat with eachfolder in subfolders
			open eachfolder
			set subfolders2 to (every folder in eachfolder whose name contains projName)
			if subfolders2 is not {} then
				repeat with eachFolder2 in subfolders2
					open eachFolder2
					
					set subfolders3 to (every folder in eachFolder2 whose name contains projName)
					if subfolders3 is not {} then
						repeat with eachFolder3 in subfolders3
							open eachFolder3
						end repeat
					end if
					
				end repeat
			end if
		end repeat
	end if
end tell

The problem is it still just searches in the root folder (Share:Client1) and doesn’t go deeper into the tree.

Here is the Output

tell application "Script Editor"
	display dialog "Projectnumber or name?" default answer ""
end tell
tell application "Finder"
	get every folder of alias "Share:Client1:" whose name contains "345"
end tell

I think the script doesn’t get the Names of the subfolders is there a workaround for that?

best regards nebu

Here is a script using ASObjC to do the job.

It may be useful if the hierarchy of subfolders may get more levels.

use AppleScript version "2.4" # Yosemite or later
use scripting additions
use framework "Foundation"

on run
	set parentFolder to choose folder
	--set parentFolder to ((path to desktop as text) & "Share:Client1")
	my germaine(parentFolder)
end run

on open sel
	my germaine(sel's item 1)
end open

on germaine(parentFolder)
	local projName, rootPosixPath, |⌘|, theFileManager, rootURL, dirAndPackageKeys
	local theEnumerator, isFolderDict, anURL, dpDictionary, PosixName
	
	set projName to the text returned of (display dialog "Projectnumber or name?" default answer "")
	
	set rootPosixPath to POSIX path of parentFolder
	set |⌘| to current application
	-- Set up an NSFileManager enumerator and get the root folder's "entire contents" (visible files and folders) as NSURLs.
	set theFileManager to |⌘|'s class "NSFileManager"'s defaultManager()
	set rootURL to |⌘|'s |NSURL|'s fileURLWithPath:(rootPosixPath)
	set dirAndPackageKeys to |⌘|'s class "NSArray"'s arrayWithArray:({|⌘|'s NSURLIsDirectoryKey, |⌘|'s NSURLIsPackageKey})
	set theEnumerator to theFileManager's enumeratorAtURL:(rootURL) includingPropertiesForKeys:(dirAndPackageKeys) options:((|⌘|'s NSDirectoryEnumerationSkipsHiddenFiles) + (|⌘|'s NSDirectoryEnumerationSkipsPackageDescendants as integer)) errorHandler:(missing value)
	set isFolderDict to |⌘|'s |NSDictionary|'s dictionaryWithObjects:({true, false}) forKeys:(dirAndPackageKeys) -- directory yes, package no
	repeat
		set anURL to theEnumerator's nextObject()
		if anURL is missing value then exit repeat
		set dpDictionary to (anURL's resourceValuesForKeys:(dirAndPackageKeys) |error|:(missing value))
		if ((dpDictionary's isEqualToDictionary:isFolderDict) as boolean) then
			set PosixName to (anURL's lastPathComponent()) as text
			if PosixName contains projName then
				tell application "Finder" to open folder (anURL as text)
			end if
		else
			--log (thisURL's |path| as text) & " is not a folder"
		end if
	end repeat
end germaine

Here the events log was :

tell application "Script Editor"
	choose folder
	display dialog "ProjectNumber or name?" default answer ""
end tell
tell application "Finder"
	open folder "SSD 500:Users:userName:Desktop:Share:Client1:Projnum234_autumn_brochure:"
	open folder "SSD 500:Users:userName:Desktop:Share:Client1:Projnum234_autumn_brochure:ProjNum234_illustration_autumn:"
end tell

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 14:52:15

Hey Yvan,

yes excuse my misstake here. The script works fine with the changes I made but it doesn’t go deeper in to the filetree then “Client1” if there is no subfolder present with the searched term say “brochure” if there is a subfolder with the term “brochure” in its pathname he goes deeper and opens every folder with “brochure” in its name. If I just search for the term “autumn” he doesn’t go into the subfolders for searching.

best regards

nebu

The one using ASObjC fills the described needs.
I didn’t took care that the string “autumn” was unavailable in the first subfolders name.

Doing the job with old-fashioned AppleScript requires “entire contents” which is very slow with the Finder.

To clean the thread I delete my original script.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 15:10:53

Hello Yvan,

the script totally works! Thanks a lot is there the possibility to say that the script only opens folders which have for numbers in front say 0000_projName. You are kind of my hero over here if you have a paypal account I would send you a little christmas gift.

One more question would it help performance wise to use subpathsOfDirectoryAtPath instead of enumeratorAtURL?

Thank you

Well seen for the use of subpathsOfDirectoryAtPath.

If I understand correctly your new question you may try :

use AppleScript version "2.4" # Yosemite or later
use scripting additions
use framework "Foundation"

on run
	set parentFolder to choose folder
	--set parentFolder to ((path to desktop as text) & "Share:Client1")
	my germaine(parentFolder)
end run

on open sel
	my germaine(sel's item 1)
end open

on germaine(parentFolder)
	local projName, rootPosixPath, |⌘|, theFileManager, rootURL, dirAndPackageKeys
	local theEnumerator, isFolderDict, anURL, dpDictionary, PosixName
	
	set projName to the text returned of (display dialog "Projectnumber or name?" default answer "")
	
	set rootPosixPath to POSIX path of parentFolder
	set |⌘| to current application
	-- Set up an NSFileManager enumerator and get the root folder's "entire contents" (visible files and folders) as NSURLs.
	set theFileManager to |⌘|'s class "NSFileManager"'s defaultManager()
	set rootURL to |⌘|'s |NSURL|'s fileURLWithPath:(rootPosixPath)
	set theNSString to |⌘|'s NSString's stringWithString:rootPosixPath
	set subFolders to theFileManager's subpathsOfDirectoryAtPath:(theNSString) |error|:(missing value)
	set subFolders to subFolders as list
	repeat with aSubFolder in subFolders
		set anURL to (|⌘|'s class "NSURL"'s fileURLWithPath:aSubFolder)
		set PosixName to (anURL's lastPathComponent()) as text
		if (PosixName contains projName) and (my replaceThis:"([0-9])([0-9])([0-9])([0-9][_])" inString:PosixName usingThis:"") ≠ PosixName then
			set NSsubFolder to (|⌘|'s NSString's stringWithString:aSubFolder)
			set fullURL to (rootURL's URLByAppendingPathComponent:NSsubFolder)
			try
				tell application "Finder" to open folder (fullURL as text)
			end try
		end if
	end repeat
end germaine

on replaceThis:thePattern inString:theString usingThis:theTemplate
	set theNSString to current application's NSString's stringWithString:theString
	set theOptions to (current application's NSRegularExpressionDotMatchesLineSeparators as integer) + (current application's NSRegularExpressionAnchorsMatchLines as integer)
	set theRegEx to current application's NSRegularExpression's regularExpressionWithPattern:thePattern options:theOptions |error|:(missing value)
	set theResult to theRegEx's stringByReplacingMatchesInString:theNSString options:0 range:{location:0, |length|:theNSString's |length|()} withTemplate:theTemplate
	return theResult as text
end replaceThis:inString:usingThis:

With this modified code I got this events log:

tell application "Script Editor"
	choose folder
		--> alias "SSD 500:Users:yvankoenig:Desktop:Share:Client1:"
	display dialog "Projectnumber or name?" default answer ""
		--> {button returned:"OK", text returned:"brochure"}
end tell
tell application "Finder"
	open folder "SSD 500:Users:yvankoenig:Desktop:Share:Client1:Projnum0123_springbrochure:"
	open folder "SSD 500:Users:yvankoenig:Desktop:Share:Client1:Projnum0123_springbrochure:extracted by Nigel's1234_brochure script under 10.11.6.rtf"
		--> error number -1728 from folder "SSD 500:Users:yvankoenig:Desktop:Share:Client1:Projnum0123_springbrochure:extracted by Nigel's1234_brochure script under 10.11.6.rtf"
	open folder "SSD 500:Users:yvankoenig:Desktop:Share:Client1:Projnum1234_autumnbrochure:"
end tell

I bet that if Shane STANLEY see this thread he will post a better code, mainly for the use of regularExpression.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 17:06:47

Hi Yvan,

sadly your new script doesn`t give me any output

The folder structure looks like this

Client1
–0324_happy
–0323_test
–test
–0212_color

if I give the test as input it should only open the “0323_test” folder. With the working script it opens both “0323_test” and the “test” folders. With the new script it doesn`t open anything at all and sadly this part of your new script goes totally over my head

on replaceThis:thePattern inString:theString usingThis:theTemplate
   set theNSString to current application's NSString's stringWithString:theString
   set theOptions to (current application's NSRegularExpressionDotMatchesLineSeparators as integer) + (current application's NSRegularExpressionAnchorsMatchLines as integer)
   set theRegEx to current application's NSRegularExpression's regularExpressionWithPattern:thePattern options:theOptions |error|:(missing value)
   set theResult to theRegEx's stringByReplacingMatchesInString:theNSString options:0 range:{location:0, |length|:theNSString's |length|()} withTemplate:theTemplate
   return theResult as text
end replaceThis:inString:usingThis:

best regards
nebu

What an ass.

I searched for characters in the range [1-9] when it would be [0-9].
I edited the script. Now it check that there is a group of 4 digits + an underscore character.
In fact it try to replace such string by an empty string. So, if there is such string, the returned string has lost five chars so it’s different that its original value.

The replaceThis handler was borrowed from Shane STANLEY’s Everyday AppleScript ObjC 3ed.pdf

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 17:42:39

Hi Yvan,

it seems to work now but I get an error like this if I hard code the partenFolder location and don’t use the choose folder dialog

error “":0212_color:0323_test" can not be transformed Typ integer” number -1700 from “:0212_color:0323_test” to integer

;(

I have no idea of which instruction returns that.

I added 5 log instructions which may help to know where is the problem.
With them I got this events log :

tell application "Script Editor"
	choose folder
		--> alias "SSD 500:Users:yvankoenig:Desktop:Share:Client1:"
end tell
(*alias SSD 500:Users:yvankoenig:Desktop:Share:Client1:*)
tell application "Script Editor"
	display dialog "Projectnumber or name?" default answer ""
		--> {button returned:"OK", text returned:"brochure"}
end tell
(*brochure*)
(*point 01 Projnum0123_springbrochure*)
(*point 02 :Projnum0123_springbrochure*)
tell application "Finder"
	open folder ":Projnum0123_springbrochure" of alias "SSD 500:Users:yvankoenig:Desktop:Share:Client1:"
end tell
(*point 03*)
(*point 01 Projnum1234_autumnbrochure*)
(*point 02 :Projnum1234_autumnbrochure*)
tell application "Finder"
	open folder ":Projnum1234_autumnbrochure" of alias "SSD 500:Users:yvankoenig:Desktop:Share:Client1:"
end tell
(*point 03*)

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 18:01:34

Hi Yvan,

the problem was that the parentFolder in the hard coded one was not defined as alias. After i defined it as alias

set parentfolder to "Share:Client1" as alias

it worked.

The problem now is that the script tries to open files with four digits in the front and the projNam and not only folders
so if there is a file present with four digits as the 4 first characters and the projNam I get an exception because Finder can’t open files just folders. Is there a way to only open folders or just strings without file extension?

best regards
nebu

It appears that using subpathsOfDirectoryAtPath wasn’t a good idea.
It returns a list of paths which may contain documents as well as folders.
I will look if I have a copy of the original code to move back to it.

I don’t retrieve the old code.
I added a try . end try so that the script doesn’t fail when it is urged to open a folder which is not a folder.
It’s a version which was already modified because I wasn’t satisfied by the code asking the Finder to open something of parentFolder

Bingo, I retrieved the code extracting only folders in message #3.
So I was able to rebuild the complete code :

use AppleScript version "2.4" # Yosemite or later
use scripting additions
use framework "Foundation"

on run
	set parentFolder to choose folder # gives an alias
	--set parentFolder to ((path to desktop as text) & "Share:Client1") as alias
	my germaine(parentFolder)
end run

on open sel
	my germaine(sel's item 1) # pass an alias
end open

on germaine(parentFolder)
	local projName, rootPosixPath, |⌘|, theFileManager, rootURL, dirAndPackageKeys
	local theEnumerator, isFolderDict, anURL, dpDictionary, PosixName
	
	set projName to the text returned of (display dialog "Projectnumber or name?" default answer "")
	
	set rootPosixPath to POSIX path of parentFolder
	set |⌘| to current application
	-- Set up an NSFileManager enumerator and get the root folder's "entire contents" (visible files and folders) as NSURLs.
	set theFileManager to |⌘|'s class "NSFileManager"'s defaultManager()
	set rootURL to |⌘|'s |NSURL|'s fileURLWithPath:(rootPosixPath)
	set dirAndPackageKeys to |⌘|'s class "NSArray"'s arrayWithArray:({|⌘|'s NSURLIsDirectoryKey, |⌘|'s NSURLIsPackageKey})
	set theEnumerator to theFileManager's enumeratorAtURL:(rootURL) includingPropertiesForKeys:(dirAndPackageKeys) options:((|⌘|'s NSDirectoryEnumerationSkipsHiddenFiles) + (|⌘|'s NSDirectoryEnumerationSkipsPackageDescendants as integer)) errorHandler:(missing value)
	set isFolderDict to |⌘|'s |NSDictionary|'s dictionaryWithObjects:({true, false}) forKeys:(dirAndPackageKeys) -- directory yes, package no
	repeat
		set anURL to theEnumerator's nextObject()
		if anURL is missing value then exit repeat
		set dpDictionary to (anURL's resourceValuesForKeys:(dirAndPackageKeys) |error|:(missing value))
		if ((dpDictionary's isEqualToDictionary:isFolderDict) as boolean) then
			set PosixName to (anURL's lastPathComponent()) as text
			if (PosixName contains projName) and (my replaceThis:"([0-9])([0-9])([0-9])([0-9][_])" inString:PosixName usingThis:"") ≠ PosixName then
				tell application "Finder" to open folder (anURL as text)
			end if
		else
			--log (thisURL's |path| as text) & " is not a folder"
		end if
	end repeat
end germaine

on replaceThis:thePattern inString:theString usingThis:theTemplate
	set theNSString to current application's NSString's stringWithString:theString
	set theOptions to (current application's NSRegularExpressionDotMatchesLineSeparators as integer) + (current application's NSRegularExpressionAnchorsMatchLines as integer)
	set theRegEx to current application's NSRegularExpression's regularExpressionWithPattern:thePattern options:theOptions |error|:(missing value)
	set theResult to theRegEx's stringByReplacingMatchesInString:theNSString options:0 range:{location:0, |length|:theNSString's |length|()} withTemplate:theTemplate
	return theResult as text
end replaceThis:inString:usingThis:

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 18:34:37