Skip to content

Instantly share code, notes, and snippets.

@verbiate
Created March 5, 2018 08:41
Show Gist options
  • Select an option

  • Save verbiate/4b9eacf12adb230aaa64ad1fba49fc22 to your computer and use it in GitHub Desktop.

Select an option

Save verbiate/4b9eacf12adb230aaa64ad1fba49fc22 to your computer and use it in GitHub Desktop.
-- Create a dialog for the user to choose from
choose from list {"Create a New Folder", "Clear an Existing Folder"} with title "Tag Folders" with prompt "Warning: selecting 'Clear an Existing Folder' will delete all folder contents." default items "Create a New Folder" OK button name "OK" cancel button name "Cancel" multiple selections allowed "false" empty selection allowed "false"
-- Set a variable called listanswer to the result of the selection as text
set listanswer to result as text
if listanswer = "Create a New Folder" or listanswer = "Clear an Existing Folder" then
tell application "Finder"
set loc to choose folder "Choose Folder Location" with prompt "Choose Output Location"
if listanswer = "Clear an Existing Folder" then
(*
We clear out the folder before we start. Using Finder
makes it easier to recover from a mistake, as deleted
files end up in the Trash.
*)
delete every item of folder loc
end if
if listanswer = "Create a New Folder" then
try
-- Make a new folder, then set it as the target folder.
set newtagfolder to "Tag Folders"
set newtagfo to make new folder at loc with properties {name:newtagfolder}
set loc2 to POSIX path of loc & newtagfolder
set loc to (POSIX file loc2) as string
on error
set theAlertText to "Unable to create new folder."
set theAlertMessage to "Make sure there's not already a folder called 'Tag Folders' at the destination and try again."
display alert theAlertText message theAlertMessage as critical buttons {"Quit"} cancel button "Quit"
end try
end if
end tell
(*
This returns all tags that are currently in use. Tags that exist
but are not in use won't be included. awk delineates each tag
with semicolons, and sed trims the final semicolon and space.
Semicolons are used as delimiters, so tags should not contain
any semicolons.
*)
set myList to do shell script "/usr/bin/mdfind -0 '(kMDItemUserTags == *)' |xargs -0 mdls -name kMDItemUserTags |grep '^ ' |cut -c5- |cut -d , -f 1 |sort -u | awk '{print}' ORS='; ' | sed '$s/..$//'"
(*
Here, we tell AppleScript to use the semicolon delimiter
we specified above. We then use this to generate a list of tags.
*)
set AppleScript's text item delimiters to "; "
set delimitedList to every text item of the myList
set AppleScript's text item delimiters to ""
-- Log the list of tags
repeat with theItem in delimitedList
log theItem
end repeat
repeat with theItem in delimitedList
tell application "Finder"
-- Create a new folder for each tag in the list
set newfolder to theItem
-- Strip quotation marks from around tags. Primarily meant for tags containing spaces.
set newfoldername to do shell script "echo " & newfolder & " | sed -e 's/^\"//' -e 's/\"$//'"
set newfo to make new folder at loc with properties {name:newfoldername}
-- Find all files that match that tag
set taggedFiles to do shell script "/usr/bin/mdfind -0 '(kMDItemUserTags == " & newfolder & ")'| tr \"\\000\" \"; \" | sed '$s/.$//'"
-- Generate a list of files matching the current tag
set AppleScript's text item delimiters to ";"
set delimitedFiles to every text item of the taggedFiles
set AppleScript's text item delimiters to ""
-- Update currentFolder to the newly created tag folder
set currentFolder to POSIX path of loc & newfoldername
log loc
log newfoldername
log currentFolder
repeat with theFile in delimitedFiles
try
-- Use -c to create clones instead of full copies. Hooray!
do shell script "cp -R -c " & quoted form of theFile & " " & quoted form of currentFolder
on error
-- Clones can only be made from the same Volume.
log "The file could not be cloned. It's likely the file is on a different Volume and can't be cloned here, or this Volume is not in APFS format and doesn't support cloned files."
end try
end repeat
end tell
log theItem
end repeat
-- Quick file path conversion for the next few commands
set posixLoc to POSIX path of loc
(*
Delete empty folders for tags not used on this Volume
(and empty subfolders). We use a shell script because
it's faster than Finder and doesn't make sound.
*)
log (do shell script "find " & quoted form of posixLoc & " -type d -empty -delete")
(*
Remove tags & labels from copied items to make sure
they don't appear twice when searching via tags.
*)
-- Remove all tags
do shell script "xattr -rd com.apple.metadata:_kMDItemUserTags " & quoted form of posixLoc
-- Remove all labels
tell application "Finder"
set loc to loc as alias
set fileList to entire contents of loc
try
repeat with i from 1 to number of items in fileList
--tell me to do shell script "mdls -name kMDItemFSLabel -raw " & quoted form of this_item
set this_item to item i of fileList
set label index of this_item to 0
end repeat
end try
end tell
else
-- Close the script if the user chooses Cancel
return
end if
@CraftedFury
Copy link

CraftedFury commented Sep 29, 2018

This no longer works on Mojave. I'm getting the following error:

error "find: -delete: /Volumes/Multimedia/Folder/xxx/Tag Folders/: relative path potentially not safe" number 1

on this line:

log (do shell script "find " & quoted form of posixLoc & " -type d -empty -delete")

Commenting out the line entirely brings up another error, and I have no clue what I'm even doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment