Moving on from a previous post, I have thought more about what I need in order to make may task easier.
Here is the folder setup
User
Documents
Clients
Client (Client-A)
Projects
Project (Project-B)
Design
Approvals
Portfolio
Production
I have named the client and project folders (Client-A & Project-B for test purposes)
You’ll notice that within the client’s project folder, there are 4 folders, Design, Approvals, Portfolio and Production.
The Script
Any files that are dragged into those 4 folders(Design, Approvals, Portfolio and Production) would automatically run a folder action script.
The script must rename the file with it’s parent (Project-B) but keep the extension. I also need to manually add a version number to the end of the name i.e. V1.
So
File-A.pdf would become Client-A V1.pdf
I have never used folder actions so I thought I would have a quick play. I have tried right clicking on the folder and clicking Services > Folder Action Setup > Run Service but it doesn’t give you the option to add your own script. How do I do this?
I’ve been accused of drip feeding my requirements rather than posting everything required. I understand why this is frustrating as an added requirement could mean a different approach to writing the script so I will try this approach instead.
I’m fairy new to Applescript and although I am starting to understand it, I don’t know where to start with this one.
before starting to code something I wish to point some details.
If I understand well you may have numerous folders named Project (akey).
As each folder contain 4 subfolders you will have to use 4 * (count projects) folder actions scripts because, if I remember well, such script may be attached to no more than a single folder.
I’m not sure that the folder actions scheme is able to apply to so many couples script/folder.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 30 juin 2020 11:53:00
That is correct, Each client’s project folder can have multiple projects i.e.
Client-A
Projects
Project-A
Design
Portfolio
Production
Approvals
Project-B
Design
Portfolio
Production
Approvals
Project-C
Design
Portfolio
Production
Approvals
As you will know, all new projects are created with a script (thanks to your help) which copies all those folders from a template folder so I guess the folder actions would need to be added to the original folders.
I’m not sure how folder actions work so, if a folder is copied does the folder action get copied with it?
Thank you.
It’s really what I guessed.
The folder actions script attached to a folder is not copied when we copy the folder.
But I was wrong on a point: a folder action may be attached to several folders.
What can’t be done is to work with several scripts attached to a folder.
In old days, attaching a script to a folder may be done with a script but I’m not sure that we may to that with not too old systems.
I will search in my archives.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 30 juin 2020 12:30:02
It seems that the content of your folder is the result of the instruction :
tell me to do shell script "cp -R " & ProjectTemplatePath & space & ProjectFolderPath
in your script New Project, VERSION 5.
Am I guessing correctly ?
If I am, it would be better to do the job directly in this script with no need for folder actions script.
Here I assume that the original items are available in the folder described by ProjectTemplatePath and that this one contain:
Design
— some files which need to be renamed in the duplicate process
Approvals
— some files which need to be renamed in the duplicate process
Portfolio
— some files which need to be renamed in the duplicate process
Production
— some files which need to be renamed in the duplicate process
I guess that because in the other thread we were asked to rename a file named blablah.md reached thru the hierarchy :
Documents
—Clients
——Amanda Rockley ESMT (AMAN01)
———Projects
————(AMAN01)-0001, Mitsubishi Outlander 2015
—————Design
——————blablah.md
The only difference is that you are now grabbing a part of the new Name from an other level in the hierarchy.
Always if I’m right, may we grab the complementary string from “(AMAN01)-0001, Mitsubishi Outlander 2015” and not from “Amanda Rockley ESMT (AMAN01)”.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 30 juin 2020 15:06:23
You are right as in the folders are already in ‘ProjectTemplatePath’ but there will be no files apart from maybe one readme file.
All files within the folders design, approval, production and portfolio will be created once the client folder and template folders have been created/copied over from the template folders.
My process is as follows…
New client
• Register Client and Create client folder
• • Create a project ready
• • • Design Project
• • • • Save design file to folder (Any name I can think of)
• • • • • Rename design file based on project name
OK but I’m always skeptical.
When the design files are ready to save,
You must know the location where you want to save them.
What need to save them with ‘old names’, attach 4 folder action scripts designed to rename them according to a substring available in the path pointing to the final location?
You have a destination whose path is something like “Maciintosh HD:Users::Documents:Clients:Amanda Rockley ESMT (AMAN01):Projects:(AMAN01)-0006, Mitsubishi Outlander 2015:"
In this folder you have already created 4 subfolders.
You have a design file whose path is something like “blablabla:fileA.ext”
You want to duplicate it in HD:Users::Documents:Clients:Amanda Rockley ESMT (AMAN01):Projects:(AMAN01)-0006, Mitsubishi Outlander 2015:Production:” with the new name
“AMAN01 V1.ext”.
This may be done easily without your convoluted scheme.
If you post a precise list of these design files giving the name of the destination subfolder I will give you the wanted script in a snap.
In fact, such script is quite ready because I already wrote a script designed to grab files from a folder whose hierarchy was:
OS Folders
—Project Template
——Approvals
———file-A.jpg
———file-A.pdf
———file-A.txt
——Design
———file-A.jpg
———file-A.pdf
———file-A.txt
——Portfolio
———file-A.jpg
———file-A.pdf
———file-A.txt
——Production
———file-A.jpg
———file-A.pdf
———file-A.txt
Complementary question, what is the nature of de “design files”?
Are they flat files or packages like some items generated by iWork ?
Packages aren’t treated exactly like flat files so, if you may have some of them additional code is required.
Back to folder actions script.
Your proposal is the worst kind of task asked to such tool.
When an attached folder actions script is asked to rename an item, the renamed object is analyzed as a newly dropped item and the script is triggered one more time.
Most of the time we may use a workaround : move the item in a subfolder before renaming it but this scheme doesn’t fit your needs.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 2 juillet 2020 10:02:01
Here is my proposal.
I commented quite each instruction so that you may easily understand what is done.
ASObjC is verbose but it’s really efficient.
-- Danjuan & YK
--> New Design
--> VERSION 8
(*
Below is an example of the hierarchy in which were previously created the design items.
The scrip is able to treat numerous design items which may be falt files or packages
OS Folders
—Project Template
——Approvals
———file-A.jpg
———file-A.pdf
———file-B.pdf -- would be a problem if changeAllName is true
——Design
———file-A.jpg
———file-A.pdf
———file-A.txt
——Portfolio
———file-A.jpg
———file-A.pdf
———file-A.txt
——Production
———file-A.jpg
———file-A.pdf - a flat file
———file-A.rtfd - a package
Select a project which need to be updated, for instance :
Clients
—Amanda Rockley ESMT (AMAN01)
——Projects
———(AMAN01)-0001, Mitsubishi Outlander 2015 <-- the selected project
————Approvals - not required
————Design - required only if it must host a ReadMe file
—————ReadMe.rtf
Execute the script.
That's all folks.
Yvan KOENIG (VALLAURIS, France) jeudi 2 juillet 2020 16:49:02
*)
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
property forYK : true
-- true -- version used by YK for tests
-- false -- more or less your code without the git part
property changeAllName : false
-- true -- change the entire name of files minus the extension
-- false -- Append the baseName at the beginning of the file names
property dropParens : true
-- true --> drop the parens surrounding baseName --> "AMAN01"
-- false --> keep the parens surrounding baseName --> "(AMAN01)"
if forYK then
set PDesignsPath to (path to desktop as string) & "Designs:OS Folders:Project Template:"
else
set PDesignsPath to (path to desktop as string) & "Designs:OS Folders:Project Template:" -- Edit to fit your needs
end if
tell application "Finder"
set ProjectFolderPath to (item 1 of (get the selection)) as string --> "SSD 1000:Users:**********:Documents:Clients:Amanda Rockley ESMT (AMAN01):Projects:(AMAN01)-0001, Mitsubishi Outlander 2015:"
end tell -- "Finder"
set baseName to my getbaseNameFrom:ProjectFolderPath
if baseName = "" then error " “" & someString & "” isn’t a project folder."
-- Define several constants
set fileManager to current application's NSFileManager's defaultManager()
set skipsPackageDescendants to current application's NSDirectoryEnumerationSkipsPackageDescendants as integer --> 2
set skipsHiddenFiles to current application's NSDirectoryEnumerationSkipsHiddenFiles as integer --> 4
set theOptions to skipsPackageDescendants + skipsHiddenFiles
set NSURLIsDirectoryKey to current application's NSURLIsDirectoryKey
set NSURLIsPackageKey to current application's NSURLIsPackageKey
set keysToRequest to {NSURLIsDirectoryKey, NSURLIsPackageKey}
-- Grab the content of the folder containing the design files
set theURLs to (fileManager's enumeratorAtURL:(PDesignsPath as «class furl») includingPropertiesForKeys:keysToRequest options:theOptions errorHandler:(missing value))'s allObjects()
if (count theURLs) = 0 then error "Le dossier “" & hfsPath & "” est vide."
-- build URL of the project to update
set projectURL to current application's NSURL's fileURLWithPath:(POSIX path of ProjectFolderPath)
-- grab the name of the project
set projectName to projectURL's lastPathComponent() as string
-- Loop duplicating the design files (or packages)
repeat with aURL in theURLs
set {theResult, isDirectory} to (aURL's getResourceValue:(reference) forKey:NSURLIsDirectoryKey |error|:(missing value))
if isDirectory as boolean then -- it's a folder or a package.
-- is this directory a package ?
set {theResult, isPackage} to (aURL's getResourceValue:(reference) forKey:NSURLIsPackageKey |error|:(missing value))
if isPackage as boolean then
set designURL to aURL -- we will duplicate it with a new name
else -- It's a folder
set designURL to missing value
end if
else -- its a flat file
set designURL to aURL -- we will duplicate it with a new name
end if
if designURL is not missing value then
-- designURL is an URL pointing upon a design item to duplicate with a new name
-- grab the URL of the folder containing the design item
set sourceFolderURL to designURL's URLByDeletingLastPathComponent()
-- grab the name of the folder containing the design item
set sourceFolderName to sourceFolderURL's lastPathComponent() as string
-- build the URL of the folder where the new design item will be stored
set destFolderURL to (projectURL's URLByAppendingPathComponent:sourceFolderName)
-- if necessary, create the destination folder
set {theResult, theError} to (fileManager's createDirectoryAtURL:destFolderURL withIntermediateDirectories:true attributes:(missing value) |error|:(reference))
-- build the new name according to the property changeAllName
if changeAllName then
-- grab the name extension of the design item
set theExt to designURL's pathExtension() as string
set newName to baseName & " V1." & theExt
else
-- grab the name of the design item
set designName to designURL's lastPathComponent() as string
set newName to baseName & " V1 " & designName
end if
-- build the URL of the newly named design item
set theNewURL to (destFolderURL's URLByAppendingPathComponent:newName)
-- try to copy the newly renamed design item
set {theResult, theError} to (fileManager's copyItemAtURL:designURL toURL:theNewURL |error|:(reference))
if (theResult as boolean) is false then
if theError's code() as integer = 516 then -- the item already exists
(fileManager's removeItemAtURL:theNewURL |error|:(reference)) -- removes the old version
set {theResult, theError} to (fileManager's copyItemAtURL:designURL toURL:theNewURL |error|:(reference))
else
error (theError's localizedDescription() as string)
end if
end if
end if -- designURL …
end repeat
display notification "The project “" & projectName & "” is updated."
#===== Now we aren't in the main code, we may put the handlers
on getbaseNameFrom:someString
-- define the pattern used by the regular expression
set pattern to "\\(([A-Z]{4}[0-9]{2})\\)"
-- build the regular expression
set regex to (current application's NSRegularExpression's regularExpressionWithPattern:pattern options:0 |error|:(missing value))
-- call the regex to search the substring mathching the given pattern
set matches to (regex's matchesInString:someString options:0 range:{location:0, |length|:(count someString)})
-- matches is an object which can't be used directly by AppleScript
-- convert the AppleScript string object into an NSString which is the official class used by ASObjC
set cocoaString to (current application's NSString's stringWithString:someString)
set baseName to "" -- in case we selected a wrong folder
repeat with aMatch in matches
-- extract the Applescript's substrings
if dropParens then
set baseName to (cocoaString's substringWithRange:(aMatch's rangeAtIndex:1)) as string --> "AMAN01"
else
set baseName to (cocoaString's substringWithRange:(aMatch's range())) as string --> "(AMAN01)"
end if
end repeat
return baseName
end getbaseNameFrom:
#=====
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 2 juillet 2020 17:08:34
I’ve tried to test it quickly but I can’t get it to work. It throws up the following error.
error "Can’t make \"Volumes:GoogleDrive:My Drive:Work:Resources:Templates:OS Folders:Project Template:\" into type constant." number -1700 from "Volumes:GoogleDrive:My Drive:Work:Resources:Templates:OS Folders:Project Template:" to constant
I tried adding my own path:
property forYK : false
if forYK then
set PDesignsPath to (path to desktop as string) & "Designs:OS Folders:Project Template:"
else
set PDesignsPath to (path to "Volumes:GoogleDrive:My Drive:Work:Resources:Templates:OS Folders:Project Template:" as string)
end if
First point, this syntax which I saw in several of your scripts is wrong.
The word “Volumes” at the very beginning of a pathname makes sense in a POSIX Path, not in an Hfs one.
Here a correct syntax would be :
set PDesignsPath to ("GoogleDrive:My Drive:Work:Resources:Templates:OS Folders:Project Template:" as string)
Point 2. This correct syntax wouldn’t be the correct needed instruction.
If I remember well, the described folder is the one where you were supposed to store the templates which you wrote that they aren’t the items which must be used here.
The needed path is the one of the folder in which, if I understood the description of your process, you built your design files.
You wrote: My process is as follows…
New client
• Register Client and Create client folder
• • Create a project ready
• • • Design Project
• • • • Save design file to folder (Any name I can think of)
• • • • • Rename design file based on project name
I understood that you create your design files in a dedicated folder from which you duplicated them to the final project folder.
It’s the only scheme which made sense because if you create these items in the “Templates:OS Folders:Project Template:” folder these design items would be annoying the next time you would use this folder.
You didn’t defined the location of this folder so I created one of my own : (path to desktop as string) & “Designs:OS Folders:Project Template:”.
In fact it’s a too much complicated path, (path to desktop as string) & “Designs:” would have been better but I already had my own “Designs” folder on my Desktop and I didn’t wished to clobber it.
I may understand that you are busy but this doesn’t prevent you to take care of what you do or write.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 3 juillet 2020 15:57:30