Applescript: add a custom tag to a folder?
MacBook Pro with Retina display, macOS High Sierra (10.13.3)
MacBook Pro with Retina display, macOS High Sierra (10.13.3)
The original Finder label index is still there for backward compatibility, but to set tags you will need to use the xattr shell utility to set a property list attribute, or some AppleScriptObjC. An AppleScriptObjC example would be something like:
use AppleScript version "2.4" -- at least Yosemite
use framework "Foundation"
use scripting additions
on run -- example
set theFile to POSIX path of (choose folder)
set theTags to (choose from list {"Testing", "Violet", "Important", "Steph", "Rouge"} with multiple selections allowed)
if theTags is not false then my addTags:theTags forFile:theFile
end run
on addTags:tagList forFile:posixPath -- add to existing tags
set theURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
set {theResult, theTags} to theURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value) -- get existing tags
if theTags is not missing value then -- add new tags
set tagList to (theTags as list) & tagList
set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete duplicates
end if
theURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forFile:The original Finder label index is still there for backward compatibility, but to set tags you will need to use the xattr shell utility to set a property list attribute, or some AppleScriptObjC. An AppleScriptObjC example would be something like:
use AppleScript version "2.4" -- at least Yosemite
use framework "Foundation"
use scripting additions
on run -- example
set theFile to POSIX path of (choose folder)
set theTags to (choose from list {"Testing", "Violet", "Important", "Steph", "Rouge"} with multiple selections allowed)
if theTags is not false then my addTags:theTags forFile:theFile
end run
on addTags:tagList forFile:posixPath -- add to existing tags
set theURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
set {theResult, theTags} to theURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value) -- get existing tags
if theTags is not missing value then -- add new tags
set tagList to (theTags as list) & tagList
set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete duplicates
end if
theURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forFile:I have revised your script, and the following works on my macOS High Sierra 10.13.3 system using one of my custom tag names. I have "hardened" the script because if an existing Finder window is not open when the script runs, it will not be able to retrieve the target of window 1 and generate an error. Now, it works.
use framework "Cocoa"
use AppleScriptversion "2.4" -- Yosemite or later
use scripting additions
property NSArray : a reference to current application's NSArray
property |NSURL| : a reference to current application's |NSURL|
property NSURLTagNamesKey : a reference to current application'sNSURLTagNamesKey
tell application "Finder"
-- target of window 1 will fail if no Finder window present, so make one if needed.
if not exists window 1 then make new Finder window to home
set projectClient to text returned of (display dialog "Nom du client:" default answer "CLIENT")
set projectName to text returned of (display dialog "Nom du projet:" default answer "PROJET")
set projectFolder to projectClient & " | " & projectName
set currentDirectory to (target of Finder window 1)
set newFolder to makenewfolderatcurrentDirectorywith properties {name:projectFolder}
set tagName to {"Seb"}
set thisFolder to (newFolder as text)'s POSIX path
my set_tag(thisFolder, tagName)
end tell
return
on set_tag(afolder, atag)
set tagArray to NSArray'sarrayWithArray:atag
set fileURL to |NSURL|'sfileURLWithPath:afolder
fileURL'ssetResourceValue:tagArrayforKey:NSURLTagNamesKey|error|:missing value
end set_tag
Unfortunately, there aren't any Automator actions to add tags, so you will need to roll your own, but fortunately, this can be done in Automator by using the Run AppleScript action. Both of our posted scripts essentially do the same thing, but it would be helpful to provide some context and/or details of the tags you are wanting to add and the actions you will be using to provide input.
Thank you guys.
This is a bit beyond my skill level.
I'm making a small applet in Automator to create and name new project folders, complete with subdirectories and an Excel workbook in just one click, in frontmost Finder window. It have it working so far.
Now I'd like to tag the folder in the process, without prompt. (Or if prompt be, to let me choose a custom tag)
Thank you
Here is the part of my script which creates the folder:
tellapplication "Finder"
setprojectClienttotext returnedof (display dialog "Nom du client:" default answer "CLIENT")
setprojectNametotext returnedof (display dialog "Nom du projet:" default answer "PROJET")
setprojectFoldertoprojectClient & " | " & projectName
setcurrentDirectorytotargetofFinder window 1
setnewFoldertomakenewfolderatcurrentDirectorywith properties {name:projectFolder}
settagNameto {"Seb"}
set_tag(newFolder, tagName)
endtell
I'd like to set a determined tag (ie. "Seb") in the process, OR ask for a tag choice ("Seb", "Steph") in a third dialog...
I can't figure out where to put the following lines
onset_tag(newFolder, tagName)
settagArraytoNSArray'sarrayWithArray:atag
setfileURLto|NSURL|'sfileURLWithPath:(POSIX pathoftheFile)
fileURL'ssetResourceValue:tagArrayforKey:NSURLTagNamesKey|error|:(missing value)
end set_tag
I
It works perfectly thank you!
On last thing (or maybe I should start another thread):
My default view options are set to : "arrange by tags".
After I successfully run the applet, the arrangement is lost.
Do you have a code to keep it arranged by Tags?
[Update:] The Finder Scripting Dictionary does not provide an arrange by tags feature. There is an arrange by label, but it does nothing. You will have to manually reset the arrangement in the Finder window toolbar by tags after each time that you run the script. Désolé pour ça.
Actually, the following produces identical results to running the whoami (or id -un) command, and never has to leave the Bash shell to produce identical results:
set tagName to (do shell script "printf '%s' $USER") as list
Result:
{"seb"}
Hi VikingOSX,
I'm a newbie to AppleScript and I was attempting a similar solution for my movie collection. Adding custom tags to Folders. I run my movie files through filebot which leaves me with this example folder/file output:
Avatar (2009) 1080p / Avatar (2009) 1080p DTS x264.mp4
After renaming using filebot I currently manually tag 1080p movies with the custom tag "1080p" and then delete the text" 1080p" from the foldername. Same process for 720p movies.
I'd like to make this process automatic 😀
I've been playing around with your script and it works for custom tagging but only for one at a time. I would like to skip the dialog box and be able to parse multiple items at once. I tried to change "set afolder to get selection" (the current selected folder/s in finder) but a can't get it to work.
Can you help me?
In what is entirely out of character for me, I have not tested the following AppleScript as there are other demands on my time today, but it shows you how to:
use framework "Cocoa"
use AppleScriptversion "2.4" -- Yosemite or later
use scripting additions
property NSArray : a reference to current application's NSArray
property |NSURL| : a reference to current application's |NSURL|
property NSURLTagNamesKey : a reference to current application'sNSURLTagNamesKey
property valid_movie : {"mp4", "mv4", "mov", "avi"}
property tag1080p : {"1080p"}
property tag720p : {"720p"}
tell application "Finder"
if not (get selection) = {} then
-- set fObject to POSIX path of (selection as text)
set fObject to (selection as text)
log fObject as text
end if
-- recursive drill into specified folder
-- set imageFiles to (every item in entire contents of folder fObject whose kind is movie and valid_movie contains name extension) as alias list
-- just files in first level of folder
set imageFiles to (every item of folder fObject whose kind is movie and valid_movie contains name extension) as alias list
repeat with anItem in imageFiles
if anItem's name contains tag1080p then
set_tag(POSIX path of anItem, tag1080p)
else if anItem's name contains tag720p then
set_tag(POSIX path of anItem, tag720p)
end if
end repeat
end tell
return
on set_tag(afolder, atag)
set tagArray to NSArray'sarrayWithArray:atag
set fileURL to |NSURL|'sfileURLWithPath:afolder
fileURL'ssetResourceValue:tagArrayforKey:NSURLTagNamesKey|error|:missing value
end set_tag
Update
Instead of compiling two different scripts, one for each user "seb" and "steph",
I found this cool workaround :
setuserNametodo shell script "whoami"
settagNameto {userName}
🙂
Since this is the same subject matter, keep using this post for questions and responses.
I will have to review the current code with the arrange by tags, and will update here when I have something.
Provided you already have custom tagnames for each username, the following is a shortcut:
set tagName to (do shell script "whoami") as list
Result:
{"seb"}
AppleScript (and Automator) only know about the default system defined color names by default, not those that we create for practical organizational reasons. There is a way to set a file or folder tag to any Finder tag, including those we create, but it requires AppleScript/Objective-C.
Here is an AppleScript/Objective-C solution that prompts you for the folder to be the tag recipient. The particular tag name is hard-coded (substitute your own) in the script. I also have a larger script that gets all system and user defined tags and places them in a list for your selection — if you want that option.
Copy and paste the following AppleScript into Script Editor (Dock : Launchpad : Other : Script Editor). Click compile, and edit the tagname list item for your particular tag. Then click run.
-- tagit.applescript
-- set one or more system or user defined tags on a file or folder
-- Revision: 1.2, Tested OS X 10.11.6, macOS 10.13.3
-- VikingOSX, 2018-02-03, Apple Support Communities
use framework "Cocoa"
use AppleScriptversion "2.4" -- Yosemite or later
use scripting additions
property NSArray : a reference to current application's NSArray
property |NSURL| : a reference to current application's |NSURL|
property NSURLTagNamesKey : a reference to current application'sNSURLTagNamesKey
property msg : "Choose the folder to receive the tag:"
property aDesktop : (path to desktop) as alias
set tagname to {"mytagname"} -- can set multiple tags at once with more list items
set afolder to (choose folderwith promptmsgdefault locationaDesktop without multiple selections allowed, invisibles and showing package contents)
set_tag(afolder, tagname)
return
on set_tag(theFile, atag)
set tagArray to NSArray'sarrayWithArray:atag
set fileURL to |NSURL|'sfileURLWithPath:POSIX path of theFile
fileURL'ssetResourceValue:tagArrayforKey:NSURLTagNamesKey|error|:missing value
end set_tag
As I mentioned, AppleScript and Automator have no clue about custom Finder tags that you may have created.
You could change:
set label index of newFolder to 1 #orange
to:
set tagname to {"Approuvé", "custom tag 2", "custom tag 3"}
set_tag(newFolder, (item 1 of tagname)) -- "Approuvé"
and add the other AppleScript items related to the use of the set_tag handler to your existing AppleScript.
As you are already using AppleScript, and presumeably, that is how you are creating your new project folder, you already have a folder name that can be passed to the set_tag handler demonstrated above. This handler can be added below your existing AppleScript as done above, and you pass your new folder name, and tagname to the handler.
You can hard-code a list of your custom Finder tagnames, but there needs to be some interaction (see choose from list) between you and the application if you want different tag names applied to folders, or an automated solution where a tagname setting logic in your script applies a specific tagname to a particular kind of project name.
Thoughts?
Applescript: add a custom tag to a folder?