diff --git a/src/Backends/Banshee.Unix/Banshee.IO.Unix/Directory.cs b/src/Backends/Banshee.Unix/Banshee.IO.Unix/Directory.cs
index 65359ce..42a4508 100644
--- a/src/Backends/Banshee.Unix/Banshee.IO.Unix/Directory.cs
+++ b/src/Backends/Banshee.Unix/Banshee.IO.Unix/Directory.cs
@@ -88,9 +88,12 @@ namespace Banshee.IO.Unix
         
         public IEnumerable<string> GetFiles (string directory)
         {
-            UnixDirectoryInfo unix_dir = new UnixDirectoryInfo (directory);
-            foreach (UnixFileSystemInfo entry in unix_dir.GetFileSystemEntries ()) {
-                if (!entry.IsDirectory && entry.IsRegularFile && !entry.IsSocket && entry.Exists) {
+            var unix_dir = TraverseSymlink(new UnixDirectoryInfo (directory)) as UnixDirectoryInfo;
+            if (unix_dir == null) {
+                yield break;
+            }
+            foreach (var entry in unix_dir.GetFileSystemEntries ()) {
+                if (entry != null && !entry.IsDirectory && entry.IsRegularFile && !entry.IsSocket && entry.Exists) {
                     yield return entry.FullName;
                 }
             }
@@ -98,14 +101,36 @@ namespace Banshee.IO.Unix
         
         public IEnumerable<string> GetDirectories (string directory)
         {
-            UnixDirectoryInfo unix_dir = new UnixDirectoryInfo (directory);
-            foreach (UnixFileSystemInfo entry in unix_dir.GetFileSystemEntries ()) {
-                if (entry.IsDirectory && entry.Exists && !entry.IsSocket) {
-                    yield return entry.FullName;
+            var unix_dir = new UnixDirectoryInfo (directory);
+            foreach (var entry in unix_dir.GetFileSystemEntries ()) {
+                var info = TraverseSymlink (entry);
+                if (info != null && info.IsDirectory && info.Exists && !info.IsSocket) {
+                    yield return info.FullName;
                 }
             }
         }
-        
+
+        private readonly HashSet<string> visited_symlinks = new HashSet<string> ();
+        private UnixFileSystemInfo TraverseSymlink (UnixFileSystemInfo info)
+        {
+            lock (visited_symlinks) {
+                visited_symlinks.Clear ();
+                while (info.IsSymbolicLink) {
+                    if (visited_symlinks.Contains (info.FullName)) {
+                        return null;
+                    }
+                    visited_symlinks.Add (info.FullName);
+                    var target = new UnixSymbolicLinkInfo (info.FullName).GetContents ();
+                    if (info.FullName.StartsWith (target.FullName)) {
+                        return null;
+                    }
+                    info = target;
+                }
+
+                return info;
+            }
+        }
+
         public void Move (SafeUri from, SafeUri to)
         {
             Mono.Unix.Native.Stdlib.rename (from.LocalPath, to.LocalPath);
diff --git a/src/Core/Banshee.Core/Banshee.IO/DirectoryScannerPipelineElement.cs b/src/Core/Banshee.Core/Banshee.IO/DirectoryScannerPipelineElement.cs
index 6535f9e..100cbe6 100644
--- a/src/Core/Banshee.Core/Banshee.IO/DirectoryScannerPipelineElement.cs
+++ b/src/Core/Banshee.Core/Banshee.IO/DirectoryScannerPipelineElement.cs
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections.Generic;
 using System.IO;
 
 using Hyena.Collections;
@@ -39,10 +40,16 @@ namespace Banshee.IO
     {
         protected override string ProcessItem (string item)
         {
-            ScanForFiles (item);
+            try {
+                ScanForFiles (item);
+            }
+            finally {
+                visited_dirs.Clear ();
+            }
             return null;
         }
         
+        private readonly HashSet<string> visited_dirs = new HashSet<string> ();
         private void ScanForFiles (string source)
         {
             CheckForCanceled ();
@@ -70,13 +77,16 @@ namespace Banshee.IO
             } else if (is_directory) {
                 try {
                     if (!Path.GetFileName (Path.GetDirectoryName (source)).StartsWith (".")) {
+                        visited_dirs.Add (source);
                         try {
                             foreach (string file in Banshee.IO.Directory.GetFiles (source)) {
                                 ScanForFiles (file);
                             }
 
                             foreach (string directory in Banshee.IO.Directory.GetDirectories (source)) {
-                                ScanForFiles (directory);
+                                if (!visited_dirs.Contains (directory)) {
+                                    ScanForFiles (directory);
+                                }
                             }
                         } catch {
                         }
