Question

I'm using an application that loads the contents of a folder of audio samples for my use. The samples I want to use however, are scattered amongst many folders on my machine, and I don't want to copy them all into a single folder first.

Aliases work just fine, and I was able to make symlinks of all the desired files, put them in a single folder, and load that folder. Excellent solution, except for one thing.

I'm going to be adding more files over time that meet the criteria I use for this application. I would love to be able to use a dynamic folder that would essentially be what "Smart Folders" are, except a real folder. A Mac "Smart Folder" is not actually a folder at all, but really just creates a "SavedSearch" file, which is unreadable except by the Finder so my application can't see into it.

Is it possible to create a true dynamic folder that will just update as the filesystem changes? Or maybe being realtime would be too much of a strain, so on a schedule? I could see maybe concocting something in Automator but... I dunno sounds a bit heavy. Love to know if there's a better way!

Was it helpful?

Solution

I have found a solution to create a dynamic "soft link" folder:

Preface:

  • $HOME is the result of the environmental variable HOME here. When you log in as user example_user, $HOME is then the path to the home folder of example_user: /Users/example_user. If $HOME appears in the text below you have to replace it yourself with /Users/your_user_name/ (e.g. saving the launch agent). If $HOME appears in a code box below (e.g. in the shell script) it will automatically expanded to your home folder by the (bash) shell while executing the script.
  • mdimport -A|sed $'s/\t\t/;/g;s/(null)//g'|tr -d \' shows a lot of metadata attributes to choose from as search criteria (e.g. kMDItemAudioBitRate or kMDItemDurationSeconds)
  • mdls /path/to/file lists all metadata attributes of a chosen file

Creating a dynamic link folder:

  • Create a shell script samples.sh in $HOME/bin/sh/ with the following content:

    #!/bin/bash
    
    # Define folders
    # Source folder (including files in subfolders)
    MusicSamples=$HOME/Music/Samples
    # Destination folder
    DrumFoldr=$HOME/Desktop/Samples
    
    # Remove orphaned soft links in the destination folder
    find $DrumFoldr -type l -exec sh -c 'for x; do [ -e "$x" ] || rm "$x"; done' _ {} +
    
    # Add soft links in destination folder depending on some criteria (here: BitRate and UserTag)
    for File in $(mdfind -onlyin $MusicSamples 'kMDItemAudioBitRate >= "44000"  && _kMDItemUserTags = "Sample"')
    do
        ln -s $File $DrumFoldr
    done
    
    # Remove soft links in the destination folder depending on some criteria (removing UserTag from original file)
    for File in $(mdfind -onlyin $MusicSamples '_kMDItemUserTags != "Sample"')
    do
        filename=$(basename "$File")
        rm $DrumFoldr/$filename
    done
    

    In the shell script define your music folder containing the sample files (in my example that's a Samples folder in the Music folder) and the "DrumFoldr" containing the soft links later (in my example that's a Samples folder on my Desktop).

    Now choose some Spotlight search criteria (in my example I have chosen the bit rate and a user defined tag "Sample" - you can define user tags by right-clicking a file > Tags... and adding a tag by just writing something. The user defined tag is then available for other files and folders.

    enter image description here

    The above shell script will add only files with a sample rate of 44000 or higher and (this is a logical and!) with the user tag "Sample" as soft link to the DrumFoldr folder. So the destination folder will not contain links to files without the Sample tag but with a sample rate of 96k or files with the Sample tag but without a kMDItemAudioBitRate (like txt files or pdfs). It also does some cleansing in the DrumFoldr folder.

    BTW: the music length can be searched/determined by using the key kMDItemDurationSeconds: kMDItemDurationSeconds <= "2".

  • Create a file usr.samplesync.plist in $HOME/Library/LaunchAgents (that means: /Users/<username>/Library/LaunchAgents/) with the content:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>usr.samplesync</string>
        <key>ProgramArguments</key>
        <array>
            <string>/bin/bash</string>
            <string>/Users/<username>/bin/sh/samples.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>StartInterval</key>
        <integer>10</integer>
    </dict>
    </plist>
    

    Replace <username> by your short user name. The shell script will be executed every 10 seconds. You can increase the interval depending on your needs and environment to higher values (e.g. 60 = 1 minute or 600 = 10 minutes)

  • Load the launch agent with:

    launchctl load $HOME/Library/LaunchAgents/usr.samplesync.plist
    

If you want to save the shell script somewhere else you have to apply the path in the plist accordingly.


Caveats:

  • the original sample files mustn't contain spaces in their paths or file names (I try to solve this restriction later)
  • the original sample files mustn't be moved or the removing of the user tag won't delete the soft link

Things to improve:

  • don't create a soft link if a proper one already exists
Licensed under: CC-BY-SA with attribution
Not affiliated with apple.stackexchange
scroll top