diff --git a/bds/source/java/ch/systemsx/cisd/bds/Utilities.java b/bds/source/java/ch/systemsx/cisd/bds/Utilities.java
index c519323e154a2af456d1bfd0d821ea8c35a31abf..948a0623a3929ddbdc73a4f9f354b0c470e6007b 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/Utilities.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/Utilities.java
@@ -16,14 +16,17 @@
 
 package ch.systemsx.cisd.bds;
 
+import java.io.File;
+
 import ch.systemsx.cisd.bds.storage.IDirectory;
 import ch.systemsx.cisd.bds.storage.IFile;
 import ch.systemsx.cisd.bds.storage.INode;
+import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 
 /**
  * Storage utility methods.
- *
+ * 
  * @author Franz-Josef Elmer
  */
 public class Utilities
@@ -31,7 +34,7 @@ public class Utilities
     /**
      * Returns a subdirectory from the specified directory. If it does not exist it will be created.
      * 
-     * @throws UserFailureException if there is already a node named <code>name</code> but which isn't a directory. 
+     * @throws UserFailureException if there is already a node named <code>name</code> but which isn't a directory.
      */
     public static IDirectory getOrCreateSubDirectory(IDirectory directory, String name)
     {
@@ -46,7 +49,7 @@ public class Utilities
         }
         throw new UserFailureException("There is already a node named '" + name + "' but which isn't a directory.");
     }
-    
+
     /**
      * Returns a subdirectory from the specified directory.
      * 
@@ -67,7 +70,7 @@ public class Utilities
         }
         return (IDirectory) node;
     }
-    
+
     /**
      * Convenient short cut for <code>{@link #getString(IDirectory, String)}.trim()</code>.
      */
@@ -81,7 +84,7 @@ public class Utilities
      * 
      * @param directory Directory of the requested file.
      * @param name Name of the file.
-     * @throws UserFailureException if the requested file does not exist. 
+     * @throws UserFailureException if the requested file does not exist.
      */
     public static String getString(IDirectory directory, String name)
     {
@@ -97,9 +100,29 @@ public class Utilities
         IFile file = (IFile) node;
         return file.getStringContent();
     }
-    
+
+    /**
+     * Lists files of given <var>directory</var>.
+     * <p>
+     * Throws an <code>EnvironmentFailureException</code> if {@link File#listFiles()} returns <code>null</code>.
+     * </p>
+     * 
+     * @param directory must be a directory.
+     */
+    public final static File[] listFiles(final File directory) throws EnvironmentFailureException
+    {
+        assert directory.isDirectory();
+        final File[] fileList = directory.listFiles();
+        if (fileList == null)
+        {
+            throw EnvironmentFailureException.fromTemplate("Was not able to list files of directory '%s'", directory
+                    .getAbsolutePath());
+        }
+        return fileList;
+    }
+
     private Utilities()
     {
     }
-    
+
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java b/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java
index c87af614b2079bd3a8ab6e6539dc352dc25be261..191eece28b395640097459fb7a0306f63df8890a 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java
@@ -23,7 +23,7 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
 
 /**
  * Abstraction of a node in a hierarchical data structure.
- *
+ * 
  * @author Franz-Josef Elmer
  */
 public interface INode
@@ -32,18 +32,27 @@ public interface INode
      * Returns the name of this node.
      */
     public String getName();
-    
+
     /**
      * Returns the parent directory of this node or <code>null</code> if it is the root node.
      */
     public IDirectory tryToGetParent();
-    
+
+    /**
+     * Copies this node to the specified directory of the file system. All descendants are also copied.
+     * 
+     * @throws UserFailureException if this or a descended node is a link referring to a node which is not this node or
+     *             a descended node.
+     * @throws EnvironmentFailureException if extraction causes an IOException.
+     */
+    public void copyTo(File directory) throws UserFailureException, EnvironmentFailureException;
+
     /**
-     * Extracts this node to the specified directory of the file system. All descendants are also extracted.
+     * Moves this node to the specified directory of the file system. All descendants are also moved.
      * 
-     * @throws UserFailureException if this or a descended node is a link referring to a node which is not this
-     *      node or a descended node. 
+     * @throws UserFailureException if this or a descended node is a link referring to a node which is not this node or
+     *             a descended node.
      * @throws EnvironmentFailureException if extraction causes an IOException.
      */
-    public void extractTo(File directory) throws UserFailureException, EnvironmentFailureException;
+    public void moveTo(File directory) throws UserFailureException, EnvironmentFailureException;
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java
index 7da7143c2e58728d539a7e50476b76fe830f45ce..29076c20f2875ff06192ed87d5624029db11a1a6 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java
@@ -23,13 +23,11 @@ import ch.systemsx.cisd.bds.storage.INode;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 abstract class AbstractNode implements INode
 {
-    protected final File nodeFile;
+    protected File nodeFile;
 
     AbstractNode(File file)
     {
@@ -43,7 +41,7 @@ abstract class AbstractNode implements INode
         }
         this.nodeFile = file;
     }
-    
+
     public String getName()
     {
         return nodeFile.getName();
@@ -60,7 +58,4 @@ abstract class AbstractNode implements INode
     {
         return nodeFile.getAbsolutePath();
     }
-    
-    
-    
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java
index 5580cd1e78cb1085f9f35b4b5e885452cc51f86e..2614c054ffa491520e1b39a987d88416d003034b 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java
@@ -16,8 +16,12 @@
 
 package ch.systemsx.cisd.bds.storage.filesystem;
 
+import java.io.IOException;
 import java.util.Iterator;
 
+import org.apache.commons.io.FileUtils;
+
+import ch.systemsx.cisd.bds.Utilities;
 import ch.systemsx.cisd.bds.storage.IDirectory;
 import ch.systemsx.cisd.bds.storage.IFile;
 import ch.systemsx.cisd.bds.storage.ILink;
@@ -42,7 +46,7 @@ class Directory extends AbstractNode implements IDirectory
 
     public INode tryToGetNode(String name)
     {
-        java.io.File[] files = nodeFile.listFiles();
+        final java.io.File[] files = Utilities.listFiles(nodeFile);
         for (java.io.File file : files)
         {
             if (file.getName().equals(name))
@@ -83,7 +87,7 @@ class Directory extends AbstractNode implements IDirectory
     public INode addFile(java.io.File file) throws UserFailureException, EnvironmentFailureException
     {
         INode node = NodeFactory.createNode(file);
-        node.extractTo(nodeFile);
+        node.moveTo(nodeFile);
         return node;
     }
 
@@ -97,10 +101,14 @@ class Directory extends AbstractNode implements IDirectory
     {
         return new Iterator<INode>()
             {
-                private java.io.File[] files = nodeFile.listFiles();
+                private java.io.File[] files = Utilities.listFiles(nodeFile);
 
                 private int index;
 
+                //
+                // Iterator
+                //
+
                 public void remove()
                 {
                     throw new UnsupportedOperationException();
@@ -118,18 +126,43 @@ class Directory extends AbstractNode implements IDirectory
             };
     }
 
-    public void extractTo(java.io.File directory) throws UserFailureException, EnvironmentFailureException
+    public final void copyTo(final java.io.File directory) throws EnvironmentFailureException
     {
-        java.io.File destination = new java.io.File(directory, getName());
-        if (destination.mkdirs() == false)
+        assert directory != null;
+        try
         {
-            throw new EnvironmentFailureException("Couldn't create directory for some unknown reason: "
-                    + destination.getAbsolutePath());
+            FileUtils.copyDirectoryToDirectory(nodeFile, directory);
+        } catch (IOException ex)
+        {
+            throw EnvironmentFailureException.fromTemplate(ex, "Couldn't copy directory '%s' to directory '%s'.",
+                    nodeFile.getAbsolutePath(), directory.getAbsolutePath());
         }
+    }
+
+    public final void moveTo(java.io.File directory) throws EnvironmentFailureException
+    {
+        assert directory != null;
+        directory.mkdirs();
+        final java.io.File destination = new java.io.File(directory, getName());
+        if (destination.exists() == false)
+        {
+            // Note that 'renameTo' does not change 'nodeFile' path
+            final boolean successful = nodeFile.renameTo(destination);
+            if (successful == false)
+            {
+                throw EnvironmentFailureException.fromTemplate("Couldn't not move directory '%s' to directory '%s'.",
+                        nodeFile.getAbsolutePath(), directory.getAbsolutePath());
+            }
+            assert nodeFile.exists() == false;
+        }
+        if (nodeFile.equals(destination) == false)
+        {
+            nodeFile = destination;
+        }
+        // Update children
         for (INode node : this)
         {
-            node.extractTo(destination);
+            node.moveTo(destination);
         }
     }
-
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java
index 1b3487f3003c745bb88fc3fce39470c31e289c6c..df72cfd9a3adacfd7b13e8f50965cc6119b9d694 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java
@@ -17,19 +17,16 @@
 package ch.systemsx.cisd.bds.storage.filesystem;
 
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 
 import ch.systemsx.cisd.bds.storage.IFile;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
-import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.utilities.FileUtilities;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 class File extends AbstractNode implements IFile
@@ -39,7 +36,7 @@ class File extends AbstractNode implements IFile
         super(file);
         assert file.isFile() : "Not a file " + file.getAbsolutePath();
     }
-    
+
     public byte[] getBinaryContent()
     {
         FileInputStream inputStream = null;
@@ -61,26 +58,35 @@ class File extends AbstractNode implements IFile
         return FileUtilities.loadToString(nodeFile);
     }
 
-    public void extractTo(java.io.File directory) throws UserFailureException, EnvironmentFailureException
+    public final void copyTo(final java.io.File directory) throws EnvironmentFailureException
     {
-        FileInputStream inputStream = null;
-        FileOutputStream outputStream = null;
         try
         {
-            inputStream = new FileInputStream(nodeFile);
-            directory.mkdirs();
-            outputStream = new FileOutputStream(new java.io.File(directory, getName()));
-            IOUtils.copy(inputStream, outputStream);
+            FileUtils.copyFileToDirectory(nodeFile, directory);
         } catch (IOException ex)
         {
-            throw new EnvironmentFailureException("Couldn't extract file '" + this + "' to directory "
-                    + directory.getAbsolutePath(), ex);
-        } finally
-        {
-            IOUtils.closeQuietly(inputStream);
-            IOUtils.closeQuietly(outputStream);
+            throw EnvironmentFailureException.fromTemplate(ex, "Couldn't not copy file '%s' to directory '%s'.",
+                    nodeFile.getAbsolutePath(), directory.getAbsolutePath());
         }
-        
     }
 
+    public final void moveTo(java.io.File directory) throws EnvironmentFailureException
+    {
+        assert directory != null;
+        final java.io.File destination = new java.io.File(directory, getName());
+        if (destination.exists() == false)
+        {
+            // Note that 'renameTo' does not change 'nodeFile' path
+            final boolean successful = nodeFile.renameTo(destination);
+            if (successful == false)
+            {
+                throw EnvironmentFailureException.fromTemplate("Couldn't not move file '%s' to directory '%s'.",
+                        nodeFile.getAbsolutePath(), directory.getAbsolutePath());
+            }
+        }
+        if (nodeFile.equals(destination) == false)
+        {
+            nodeFile = destination;
+        }
+    }
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java
index 87deccea4553589f18214cb01c1d7be46ad92ff1..142224cef7d453efb2a17aa2294ce1bae33ec8db 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java
@@ -25,15 +25,15 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 class Link implements ILink
 {
 
     private final String name;
+
     private IDirectory parent;
+
     private final INode reference;
 
     Link(String name, INode reference)
@@ -51,7 +51,7 @@ class Link implements ILink
     {
         parent = parentOrNull;
     }
-    
+
     public IDirectory tryToGetParent()
     {
         return parent;
@@ -62,9 +62,15 @@ class Link implements ILink
         return reference;
     }
 
-    public void extractTo(File directory) throws UserFailureException, EnvironmentFailureException
+    public void copyTo(File directory) throws UserFailureException, EnvironmentFailureException
     {
         // TODO Auto-generated method stub
     }
 
+    public void moveTo(File directory) throws UserFailureException, EnvironmentFailureException
+    {
+        // TODO Auto-generated method stub
+
+    }
+
 }
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java
index 82169ce3f18ee21545778ba8e7eb004f0d4ed65c..9359038b506db64759bd0b0fa0cedc8721f9c2f2 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java
@@ -22,13 +22,11 @@ import ch.systemsx.cisd.bds.storage.INode;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 class NodeFactory
 {
-    static INode createNode(java.io.File file)
+    static INode createNode(java.io.File file) throws EnvironmentFailureException
     {
         assert file != null : "Unspecified node";
         String absolutePath = file.getAbsolutePath();
@@ -49,7 +47,7 @@ class NodeFactory
             throw new EnvironmentFailureException("Couldn't get canonical path of file " + absolutePath);
         }
     }
-    
+
     private NodeFactory()
     {
     }
diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/DirectoryTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/DirectoryTest.java
index 2d87700aa09052b386510d79b705d20a4846c7a2..3391d1b9e06bb2116ee6e0f1ff75dabf634ace77 100644
--- a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/DirectoryTest.java
+++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/DirectoryTest.java
@@ -33,8 +33,6 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.utilities.FileUtilities;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class DirectoryTest extends StorageTestCase
@@ -45,32 +43,32 @@ public class DirectoryTest extends StorageTestCase
         Directory directory = new Directory(TEST_DIR);
         assertEquals(TEST_DIR.getName(), directory.getName());
     }
-    
+
     @Test
     public void testMakeDirectory()
     {
         Directory directory = new Directory(TEST_DIR);
         IDirectory subdirectory = directory.makeDirectory("sub-directory");
-        
+
         assertEquals("sub-directory", subdirectory.getName());
         File subdir = new File(TEST_DIR, "sub-directory");
         assertEquals(true, subdir.exists());
         assertEquals(true, subdir.isDirectory());
     }
-    
+
     @Test
     public void testMakeDirectoryTwice()
     {
         Directory directory = new Directory(TEST_DIR);
         directory.makeDirectory("sub-directory");
         IDirectory subdirectory = directory.makeDirectory("sub-directory");
-        
+
         assertEquals("sub-directory", subdirectory.getName());
         File subdir = new File(TEST_DIR, "sub-directory");
         assertEquals(true, subdir.exists());
         assertEquals(true, subdir.isDirectory());
     }
-    
+
     @Test
     public void testMakeDirectoryButThereIsAlreadyAFileWithSameName()
     {
@@ -85,7 +83,7 @@ public class DirectoryTest extends StorageTestCase
             assertTrue(e.getMessage().indexOf("sub-directory") >= 0);
         }
     }
-    
+
     @Test
     public void testAddKeyValuePair()
     {
@@ -93,9 +91,32 @@ public class DirectoryTest extends StorageTestCase
         assertEquals("42\n", FileUtilities.loadToString(new File(TEST_DIR, "answer")));
         assertEquals("42\n", stringFile.getStringContent());
     }
-    
+
+    @Test
+    public void testCopyTo()
+    {
+        File dir = new File(TEST_DIR, "dir");
+        dir.mkdirs();
+        Directory directory = new Directory(dir);
+        directory.addKeyValuePair("p1", "property 1");
+        IDirectory subdir = directory.makeDirectory("subdir");
+        subdir.addKeyValuePair("p2", "property 2");
+        File destination = new File(TEST_DIR, "destination");
+        assertFalse(destination.exists());
+        directory.copyTo(destination);
+        assertTrue(destination.exists());
+        File copiedDir = new File(destination, "dir");
+        assertTrue(copiedDir.exists());
+        assertEquals("property 1\n", FileUtilities.loadToString(new File(copiedDir, "p1")));
+        File copiedSubDir = new File(copiedDir, "subdir");
+        assertTrue(copiedSubDir.isDirectory());
+        assertEquals("property 2\n", FileUtilities.loadToString(new File(copiedSubDir, "p2")));
+        // Source directory still exists
+        assertEquals(true, new File(TEST_DIR, "dir").exists());
+    }
+
     @Test
-    public void testExtractTo()
+    public void testMoveTo()
     {
         File dir = new File(TEST_DIR, "dir");
         dir.mkdirs();
@@ -105,9 +126,7 @@ public class DirectoryTest extends StorageTestCase
         subdir.addKeyValuePair("p2", "property 2");
         File destination = new File(TEST_DIR, "destination");
         assertFalse(destination.exists());
-        
-        directory.extractTo(destination);
-        
+        directory.moveTo(destination);
         assertTrue(destination.exists());
         File copiedDir = new File(destination, "dir");
         assertTrue(copiedDir.exists());
@@ -115,8 +134,10 @@ public class DirectoryTest extends StorageTestCase
         File copiedSubDir = new File(copiedDir, "subdir");
         assertTrue(copiedSubDir.isDirectory());
         assertEquals("property 2\n", FileUtilities.loadToString(new File(copiedSubDir, "p2")));
+        // Source directory does no longer exist
+        assertEquals(false, new File(TEST_DIR, "dir").exists());
     }
-    
+
     @Test
     public void testAddFile()
     {
@@ -129,9 +150,9 @@ public class DirectoryTest extends StorageTestCase
         File dest = new File(TEST_DIR, "destination");
         dest.mkdir();
         Directory directory = new Directory(dest);
-        
+
         INode copiedDir = directory.addFile(dir);
-        
+
         assertEquals("dir", copiedDir.getName());
         assertTrue(copiedDir instanceof IDirectory);
         File copiedRealDir = new File(dest, "dir");
diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/FileTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/FileTest.java
index 29346c1a6180a935c02cb1bc497d70505f795096..43773505c9f59e1630a8b790b836a371b9b55023 100644
--- a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/FileTest.java
+++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/FileTest.java
@@ -23,8 +23,6 @@ import org.testng.annotations.Test;
 import ch.systemsx.cisd.common.utilities.FileUtilities;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class FileTest extends StorageTestCase
@@ -40,7 +38,7 @@ public class FileTest extends StorageTestCase
         assertEquals("Hello\nworld!\n", stringFile.getStringContent());
         assertEquals("Hello\nworld!\n", new String(stringFile.getBinaryContent()));
     }
-    
+
     @Test
     public void testExtractTo()
     {
@@ -49,7 +47,8 @@ public class FileTest extends StorageTestCase
         File stringFile = new File(file);
 
         java.io.File subdir = new java.io.File(TEST_DIR, "subdir");
-        stringFile.extractTo(subdir);
+        stringFile.copyTo(subdir);
         assertEquals("Hello\nworld!\n", FileUtilities.loadToString(new java.io.File(subdir, stringFile.getName())));
     }
+
 }
diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/StorageTestCase.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/StorageTestCase.java
index 0e2b052ebd1fefbef18bd3433632df288facb2cb..647b3c55b9fb01b72c62a4b099330b09a23d8f9e 100644
--- a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/StorageTestCase.java
+++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/StorageTestCase.java
@@ -23,19 +23,17 @@ import org.apache.commons.io.FileUtils;
 import org.testng.annotations.BeforeMethod;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class StorageTestCase
 {
     static final File TEST_DIR = new File("targets" + File.separator + "unit-test-wd");
-    
+
     @BeforeMethod
     public void setup() throws IOException
     {
         TEST_DIR.mkdirs();
         FileUtils.cleanDirectory(TEST_DIR);
     }
-    
+
 }