Hello,
My longer used libraries seem to collect large number of tags listed in sidebar, which only few may be still used. Is there any way to identify and delete the tags which are no more used? There is Apple script from 2013 in one of the contributions here, but that seems to be asking for Growl, which is retired by now.
I’ve updated the script to use EagleFiler’s built-in notification feature instead of Growl. However, when I tested the script on one of my libraries it incorrectly identified lots of tags as being unused. I’ve not used the script before and haven’t had time to look into what the problem might be. But I’m posting the work in progress in case you find this helpful.
-- identify-unused-tags.scpt v. 04
-- Purpose: identify tags not assigned to any record
-- Usage notes:
-- CAUTION: E-mail messages in mailboxes are not currently available via AppleScript. So the script will find, as 'unused', tags that are not used by files (including messages outside of mailboxes) but which -are- used by messages in mailboxes. [per Michael Tsai] If the library contains a mailbox (empty or not), the last "Growl" notification reminds you to check the unused tags for mail messages.
-- Unused tags do not include 1) built-in EF tags and 2) user-specified "permanent" tags. User-specified permanent tags start with "!_"; other customizations are possible.)
-- The script operates on -all- library records -- i.e., record selection is ignored.
-- Do not change or close front library until script completes. (You can switch to other applications.)
-- For Growl 1.x, adjust Growl test as indicated below.
-- After running the script, check each "unused" tag to ensure it is empty.
-- Author: humanengr
-- Available from: the EagleFiler forum (http://c-command.com/forums/forumdisplay.php?f=7)
-- Last Modified: 2013-03-23
-- Version history
-- v. 04
-- Michael removed Growl dependency.
-- v. 03
-- Added code for running w/o Growl.
-- v. 02
-- Addressed a garbage collection issue. (Some unused tags were overlooked in older libraries.)
-- v. 01
-- Fixed mistaken classification as "unused" of empty parent tag with -multiple- used child tags.
-- Fixed case sensitivity -- unused tags with different case than a used tag are now classified as "unused".
-- v. 00
tell application "EagleFiler"
notify with name "Progress" title "Getting list of all the tags" description "in the library's list of tags"
considering case
-- Get names of document tags
set _documentTags to front document's tags
set _documentTagNames to {}
repeat with _tag in _documentTags
set end of _documentTagNames to (name of _tag)
end repeat
notify with name "Progress" title "Collecting tags used in records ..." description "(this might take a minute or two)"
-- Collect tags used in all library records
-- Set _records to every library record of document 1
-- and check if there are any mailboxes in the library
set _records to every library record of front document
set _usedTags to {}
set _usedTagNames to {}
repeat with _record in _records
if id of _record is not 2 then -- record is not "Trash"
set _usedTags to _usedTags & assigned tags of _record
set _usedTagNames to _usedTagNames & assigned tag names of _record
end if
end repeat
-- Include the entire parental hierarchy of any used tags
-- Initialize
set _tagsToTestForParents to _usedTags -- Begin by testing all used tags
set _testForNewParents to "yes"
set _newParents to {}
set _newParentsNames to {}
-- Move up the hierarchy for each used tag
repeat until _testForNewParents is "no"
-- Test each used tag to see if it has a tag parent
repeat with _tag in _tagsToTestForParents
if (_tag's container is not missing value and _usedTagNames does not contain (name of _tag's container) as text) then
-- Collect parents
if name of _tag's container is not in _newParentsNames then
set end of _newParents to _tag's container
set _newParentsNames to _newParentsNames & (name of _tag's container) as text
end if
end if
end repeat
-- Add parents to used tags
if (count of _newParents) > 0 then
set end of _usedTags to _newParents
set end of _usedTagNames to _newParentsNames
end if
-- Reset set of tags to test to the newly discovered parents
set _tagsToTestForParents to _newParents
-- If no new parents were discovered, end the loop
if (count of _newParents) is 0 then set _testForNewParents to "no"
-- Reinitialize
set _newParents to {}
set _newParentsNames to ""
end repeat
notify with name "Progress" title "Removing dupes, sorting, and" description "identifying unused tags"
-- Remove dupes and sort the list
set _usedTagNames to my DeDupeAndSort(_usedTagNames)
-- Compare lists to create list of unused tags
set _unusedTags to {}
repeat with _TagName in _documentTagNames
if _TagName is not in _usedTagNames then
set _unusedTags to (_unusedTags & _TagName)
end if
end repeat
_usedTagNames
-- Ignore permanent EF tags
set _permanentTags to {"note", "__deleted__", "flagged", "unread"}
-- Ignore "permanent" user-specified tags -- assumed to start with "!_"
set _tagsToDelete to {}
repeat with i from 1 to count _unusedTags
if ({_unusedTags's item i} is not in _permanentTags and _unusedTags's item i does not contain "!_") then set _tagsToDelete's end to _unusedTags's item i
end repeat
-- Alternate code for "permanent" user-specified tags
-- set _permanentTags to _permanentTags & {"PermanentTag1", "PermanentTag2", …}
-- Create an "unused" tag to contain the tags to delete
tell front document
set _countUnused to 0
repeat with _name in _tagsToDelete
if _name is not "unused" then
set _tag to tag _name
repeat with _subtag in _tag's tags
-- Don't want to get rid of subtags that might be in use
set _subtag's container to _tag's container
end repeat
set _tag's container to tag "unused"
set _countUnused to _countUnused + 1
end if
end repeat
end tell
tell front document
if exists (library records whose universal type identifier is "com.c-command.mbox") then
set _description to "Check tags for mail messages"
else
set _description to ""
end if
end tell
if _countUnused is 0 then
set _title to "No unused tags found"
set _description to ""
else
set _title to (_countUnused as text) & " unused tags found"
end if
notify with name "Done" title _title description _description
end considering
end tell
-- DJ Bazzie Wazzie, http://macscripter.net/viewtopic.php?id=37449
on DeDupeAndSort(theList)
set AppleScript's text item delimiters to {ASCII character 10}
set theString to theList as string
set AppleScript's text item delimiters to ""
set sortedList to paragraphs of (do shell script "/bin/echo " & quoted form of theString & "| sort -fu") -- removed -n (do not print trailing newline character) from echo; added -f (ignore case) to sort.
end DeDupeAndSort
The script seems to find the tag uses by looping over all the records and making a list of the used tag names. I would suggest a different approach of asking EagleFiler how many records use each tag. And that should be a lot faster so that you don’t need the progress notifications. Here’s a proof of concept:
tell application "EagleFiler"
tell library document 1
set _tags to tags
repeat with _tag in _tags
if (count of _tag's library records) is 0 then
display dialog "Tag “" & _tag's name & "” seems to be unused (except possibly by messages within mailboxes)."
end if
end repeat
end tell
end tell
This could be adapted to move the tags to an unused parent, as in the original script.
Hello Michael,
yes, this seems to work just fine for me. Thank you for your help!
tell application "EagleFiler"
tell library document 1
set _tags to tags
repeat with _tag in _tags
if (count of _tag's library records) is 0 then
#display dialog "Tag “" & _tag's name & "” seems to be unused (except possibly by messages within mailboxes)."
set _tag's container to tag "unused"
end if
end repeat
end tell
end tell
Great! If, for some reason, it moves a tag that you didn’t want (e.g. because it was used by messages in a mailbox) you can Undo (perhaps multiple times), and the tags should move back to their original locations.