Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Create symbolic links from multiple sets of source folders System
I have a ridiculously large media library, spread across multiple drives. By way of example: drive X, drive Y and drive Z all contain TV Shows directories, and trying to remember which drive's TV Shows directory contains which actual television show is a hassle I'm too lazy to put up with.

I wanted a global TV Shows folder containing the content of each individual drive's own TV Shows folder. Using Smart Folders or aliases presented a few drawbacks, as a lot of applications (not to mention other operating systems) don't understand them, so creating symbolic links (symlinks) was the best option.

The following AppleScript creates symlinks into a single folder from multiple sources
-- Gets the folder list of any number of specified source directories, and creates matching symlinks for each in a single specified directory.
-- Written by Dave Chevell, 2nd of May, 2010. Yay me.

-- The sourceList variable contains the list of folders from which to source your symlinks. As you can see in the following example, they must be separated by commas and contained by "double quotes"
set sourceList to {"/Volumes/Disk X/TV Shows/", "/Volumes/Disk Y/Television shows/", "/Users/Dave/Media/TV Shows/", "/Volumes/Disk Z/video/tvshows/"}

-- The destinationFolder variable is where your symbolic links will be created. The actual folder must exist
set destinationFolder to "/Users/Dave/Desktop/TV Shows/"

-- Whether or not you end your sources or your destination folder with a forward slash, the script accounts for it by adding an extra one. This appears to work without issue (OS X 10.6.3)

repeat with currentSource in sourceList
  
  tell application "Finder"
    
    set sourceFolders to get name of folders of folder (currentSource as POSIX file)
    
    repeat with currentFolder in sourceFolders
      
      
      -- Even if your sourceList or destinationFolder variable entries end in a forward slash, adding another forward slash in this next step "just in case" still appears to work (tested only on OS 10.6.3)
      set fromPath to currentSource & "/" & currentFolder
      set toPath to destinationFolder & "/" & currentFolder
      
      
      -- Escape out characters the terminal does not like in file paths.. for some reason making strings "quoted form of" doesn't work with symlinks, so we have to parse each path and add escape characters instead. New escape characters can be added to the illegalChars variable. They must be separated by commas and contained by "double quotes"
      set illegalChars to {" ", "&", "'"}
      
      repeat with delimChar in illegalChars
        if fromPath contains delimChar or toPath contains delimChar then
          
          set AppleScript's text item delimiters to delimChar
          set the pathText to every text item of fromPath
          set AppleScript's text item delimiters to the "\\" & delimChar
          set fromPath to the pathText as string
          
          set AppleScript's text item delimiters to delimChar
          set the pathText to every text item of toPath
          set AppleScript's text item delimiters to the "\\" & delimChar
          set toPath to the pathText as string
          
        end if
        
      end repeat
      
      
      -- Finally, create the damned link. "Try" is used so we can skip errors about existing symlinks
      try
        do shell script "ln -s " & fromPath & " " & toPath
      end try
      
    end repeat
  end tell
end repeat
Before you do anything, create the destination folder somewhere -- you can't create symlinks in a non-existent location!

The script only works for folders, not files. Since the actual symlink creation is done via do shell script, it will appropriately escape spaces, ampersands (i.e. the "&" character), and single quotes. If you can think of other characters that need to be escaped, let me know -- they're very easy to add to the script.

This script can safely be re-run to update your destination folder with new symlinks.

If anyone has advice on either modifying the script so it works on folders and files at the same time, please chime in! To be honest, I haven't trawled google to work out what to do for files instead of folders, so if you have a tip for that, sound off in the comments.

[crarko adds: I haven't tested this one, but did make sure the code compiled as valid AppleScript.]
    •    
  • Currently 2.00 / 5
  • 1
  • 2
  • 3
  • 4
  • 5
  (10 votes cast)
 
[7,163 views]  

Create symbolic links from multiple sets of source folders | 3 comments | Create New Account
Click here to return to the 'Create symbolic links from multiple sets of source folders' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Create symbolic links from multiple sets of source folders
Authored by: fracai on May 05, '10 08:02:44AM
This sounds quite a bit like functionality that is provided by GNU Stow. Stow is intended for managing software, but would be equally applicable to linking media.
---
i am jack's amusing sig file


[ Reply to This | # ]
Create symbolic links from multiple sets of source folders
Authored by: klatt on May 05, '10 11:57:53AM

THANK YOU!!!!! I do not normally go all caps but I've totally been looking for something like this. THANK YOU.



[ Reply to This | # ]
Create symbolic links from multiple sets of source folders
Authored by: CarlRJ on May 05, '10 04:13:34PM
Not to pick on AppleScript, but a scripting language like Perl (or Python, or Ruby, or...) can bypass a lot of the quoting gymnastics by talking directly to the kernel for things like symlink creation, rather than passing commands through the shell. This version is a bit more robust (it'll complain on errors, create symlinks to both files and folders found in the folders listed in sourceList, and as mentioned, obviates the need for escaping characters; it'll also tell what it's doing, if you remove the "#" before "print" towards the end); otherwise it's much the same, but in Perl...

#!/usr/bin/perl
use strict;
use warnings;

my @sourceList = (
    "/Volumes/Disk X/TV Shows",
    "/Volumes/Disk Y/Television shows",
    "/Users/Dave/Media/TV Shows",
    "/Volumes/Disk Z/video/tvshows"
);
my $destinationFolder = "/Users/Dave/Desktop/TV Shows";

foreach my $currentSource (@sourceList) {

    opendir SDIR, $currentSource  or do {
	warn "$0: can't opendir $currentSource: $!\n";
	next;
    };
    my @sourceFolders = grep { not /^\.{1,2}$/ } readdir SDIR;
    closedir SDIR;

    foreach my $currentFolder (sort @sourceFolders) {

	my $fromPath = $currentSource     . '/' . $currentFolder;
	my $toPath   = $destinationFolder . '/' . $currentFolder;

	if (not -e $toPath) {
	    # print "Creating $toPath as symlink to $fromPath\n";
	    symlink $fromPath, $toPath
		or warn "$0: can't symlink $toPath to $fromPath: $!\n";
	}
    }
}
Edited on May 05, '10 04:15:15PM by CarlRJ


[ Reply to This | # ]