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?
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?
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
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.
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?
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.
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:
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
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?
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: