How do I keep a Mac folder with aliases synced with the original? Halp!
December 1, 2021 11:07 AM   Subscribe

Hello! I am a musician who manages a set of files (plugins) on my computer in a specific way. I install them into one big folder (as Ableton prefers) and then I have a separate folder with category subfolders and aliases of the original files and then point Ableton to the aliases folder. I would like to keep these in sync with a script so that everything (and only the things) in the original folder is in the aliases folder. Of course, there are challenges to syncing two folders that aren't exact duplicates but should have the same number of identically named files.

My current process involves

1. Install Plugins (typically a single file with a .vst extension) to /Library/Audio/Plug-ins/VST (as my software prefers)

2. I have a Folder in my /Documents where I have aliases of the VST files, sorted into separate subfolders (e.g. /Documents/VST/Reverb, /Documents/VST/Delay)

3. I point my audio software at the aliases folder and am then able to navigate them in an organized fashion within the app interface.


What I'm trying to solve for:
1. I will often forget to create aliases in the alias folder which means Ableton doesn't know about new plugins I install. This is unlikely to change
2. I will sometimes remove plugins from the original folder and not necessarily remember to remove the alias, which means Ableton links to a non-existent plugin which can sometimes cause problems.


I would love to have a script (or several scripts) to compare the contents of /Library/Audio/Plug-ins/VST and /Library/Audio/Plug-ins/VST (including its subdirectories) and then do these two things:
- If any files in the former dont have aliases, create them in an "unsorted" subfolder
- If any aliases in the latter refer to non-existent files, move them to the trash.

Is this possible? I'm thinking it might have a little bit of extra complexity because its not an exact replica? (i.e. something like /vst/samplereverb.vst would have an alias in /documents/vst/reverb/samplereverb.vst)


A clunky way I've thought about doing it is
1. Create a text file of all the files in /plug-ins/VST and subdirectories sorted alphabetically into a flat list.
2. Create a text file of all the files in /documents/VST and subdirectories sorted alphabetically into a flat list.
3. Compare lists
4. Anything that is in list 1 and not in list 2, create an alias in an "unsorted" folder
5. Anything that is in list 2 and not in list 1, move to trash


I'm hoping to use automator or a shell script to do this automatically at regular intervals.
posted by softlord to Technology (7 answers total)
 
Can there be subfolders in ~/Library/Audio/Plug-ins/VST/?

If so, why not organize them there, and then just put an alias to ~/Library/Audio/Plug-ins/VST in ~/Documents/VST?
posted by vitout at 11:31 AM on December 1, 2021 [1 favorite]


If you are on a Mac, this would be a sideways approach compared to what you're doing, but how about using Finder tags? MacOS actually has a customizable taxonomy system (so you could have not only tags but other taxonomic systems), but tags are built right in, and you can assign them when you're saving a file, or by right-clicking on an existing file.

This way, you could leave all your plugins in the big folder, and rather than breaking out separate folders full of aliases for future navigation, you'd just navigate to the big folder and click on the desired tag in the Open File window's sidebar to filter your results. Note that you need to have tags turned on in the sidebar, obviously. Assuming you set colors for your VST tags, it will be obvious just by looking at the folder in the Finder what you've left untagged.

There is a lot of third-party Mac software for dealing with tags, and tags are scriptable with AppleScript and accessible from the command line, if you want to get into that.

You can do something similar by adding category names directly to the filename. I'd encapsulate the category names in {braces} or something to avoid naming collisions. Then do a search in the Finder for "name contains {category}", save that search, and add it to the sidebar when saving. It will then appear under Favorites in the sidebar. You don't even need to navigate to the big folder if you do that—just click on the sidebar item.
posted by adamrice at 11:53 AM on December 1, 2021


Response by poster: @vitout Putting subfolders within the main folder can cause trouble both with software updates writing to the wrong folder and with some plugins not working (as they expect to be in the root of the plugin folder)
posted by softlord at 12:01 PM on December 1, 2021


Response by poster: @adamrice this would work except that I do not believe Ableton (or Bitwig which i also use) can use finder tags to organize things.

To clarify, the reason i put them in separate folders is so that the software's internal browser sorts them correctly rather than in one big list.
posted by softlord at 12:02 PM on December 1, 2021


So, do they have to be Aliases, or will symbolic links work? It's a lot easier to knock up a shell script to handle this if symlinking works... I mean, I say "easy", but compared to telling Applescript to do a thing, "ln -s" is almost straightforward.
posted by Kyol at 2:13 PM on December 1, 2021 [1 favorite]


I agree with @Kylo, using symbolic links might be a good way to go.

At a high level this is what I’d do.

First I’d forget about comparing the two folders and just rebuild the whole /Library/Audio/Plug-ins/VST from /Documents/VST. Comparing the two would add a ton of unnecessary complexity

“find ~/Documents/VST” would list all of the files including subdirectories and from there you’d just need a loop to run “ln -s” for each file.

This is just a broad overview and the commands above are incomplete, but hopefully it can give you a place to start 😃
posted by _benj at 1:45 AM on December 2, 2021


Response by poster: To close the loop on this, someone in the Apple forums kindly created an Applescript that does pretty much what i wanted. Please note the in-thread caveats and setup if you'd like to use it yourself.


==


--define global variables:
global unsortedName
global deletionsName
global confirmedAliases
global pluginsPath
global aliasesPath
global deletedAliasesPath
global unsortedPath
global reportFilePath
global deletionsName
global pluginsreportText
global createdAliasesText
global aliasPlugins
global originalPlugins

--define text strings and empty lists:
on run
my defineText()
my definePaths()
my prepare()
my filterorphans()
my createAliases()
my writeReport()
end run

on defineText()
--set up text strings for path creation and report
set today to current date
set todayString to ((day of today as string) & " " & month of today as string) & " " & year of today as string
set pluginsreportText to "Orphan aliases ready for deletion, " & todayString & ":" & return
set createdAliasesText to "Aliases created for the following plug-ins, " & todayString & ":" & return
set unsortedName to "Unsorted"
set deletionsName to "Aliases for deletion"
set confirmedAliases to {} -- create empty list which will contain references to aliases that do have originals
end defineText

on definePaths()
--define paths to VST plugins folder, aliases folder, 'deletiohs' folder, 'unsorted' folder and report file:
set pluginsPath to (path to library folder from local domain as string) & "Audio:Plug-ins:VST:" as alias -- define path to plugins
set aliasesPath to (path to documents folder from user domain as string) & "VST:" --define top-level folder containing aliases
set deletedAliasesPath to aliasesPath & deletionsName & ":"
set unsortedPath to aliasesPath & unsortedName & ":" -- define path to Unsorted folder
set reportFilePath to aliasesPath & "VST plug-ins report:" -- define path to report
end definePaths

on prepare()
--prepare file lists, create Unsorted and Deletions folders if necessary:
set pluginsList to {}
set originalPlugins to my listPlugins(pluginsList, pluginsPath)
tell application "Finder"
set aliasPlugins to entire contents of folder aliasesPath -- including folders, which will be filtered out later
try
make folder in folder aliasesPath with properties {name:unsortedName} --if this errors, the folder already exists
end try
try
make folder in folder aliasesPath with properties {name:deletionsName} --as above
end try
end tell
end prepare

on listPlugins(pluginsList, pluginsPath)
--recurse through folders in the Plugins:VST folder to create a list of every .VST file (including those in subdirectories:
tell application "System Events"
set folderList to every item of pluginsPath
repeat with eachItem in folderList
if class of eachItem is folder then
set eachItem to path of eachItem as alias
my listPlugins(pluginsList, eachItem)
else
if name extension of eachItem is "VST" then set end of pluginsList to path of eachItem
end if
end repeat
end tell
return pluginsList
end listPlugins

on filterorphans()
--filter out "orphaned" aliases and move them to deletion folder:
repeat with eachItem in aliasPlugins
tell application "Finder"
if class of eachItem is alias file then -- only process alias files
try
set originalPlugin to original item of eachItem --test for original
set end of confirmedAliases to eachItem -- test passed, so add this alias to list of aliases which do have originals
on error --test failed, the alias has no original item, so ...
set pluginsreportText to pluginsreportText & name of eachItem & return --add the name of the deleted alias to the report
move eachItem to folder deletedAliasesPath with replacing
--alternatively:
--delete eachItem
end try
end if
end tell
end repeat
end filterorphans

on createAliases()
--create aliases to plug-in files which don't have them:
-- update report text:
set pluginsreportText to pluginsreportText & return & createdAliasesText
tell application "Finder"
repeat with x from 1 to count originalPlugins
set eachPlugin to item x of originalPlugins -- get a Finder reference to each plugin in turn
set pluginHasAlias to false -- assume that the plugin does not have an alias
repeat with eachAlias in confirmedAliases -- check the plugin against every confirmed alias
if original item of eachAlias is eachPlugin then -- the plugin DOES have an alias so...
set pluginHasAlias to true
exit repeat --no need to check further
end if
end repeat
if not pluginHasAlias then -- this plugin does NOT have an alias so...
set pluginsreportText to pluginsreportText & name of file eachPlugin & return -- update report
make alias file at folder unsortedPath to eachPlugin -- create the alias in the Unsorted folder
end if
end repeat
end tell
end createAliases

on writeReport()
--write report to text file:
set pluginsReportFile to (open for access file reportFilePath with write permission)
try
write pluginsreportText to pluginsReportFile starting at eof
on error
close access pluginsReportFile
end try
close access pluginsReportFile
tell application "Finder" to open file reportFilePath
end writeReport
posted by softlord at 2:23 PM on January 2, 2022


« Older I can't see backwards!   |   Song lyrics ID help, and a bonus... Newer »
This thread is closed to new comments.