diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/FileUtilities.java b/common/source/java/ch/systemsx/cisd/common/utilities/FileUtilities.java
index 9613e7cf703164aefb7a5a1eb7236d2cad1486dd..a4fd2b8c61c35e661bb3886e60a49c931d06a3fc 100644
--- a/common/source/java/ch/systemsx/cisd/common/utilities/FileUtilities.java
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/FileUtilities.java
@@ -25,9 +25,11 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
-import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
 
@@ -210,6 +212,7 @@ public final class FileUtilities
     /**
      * Checks whether a <var>path</var> of some <var>kind</var> is fully accessible to the program.
      * 
+     * @param kindOfPath description of given <var>path</var>. Mainly used for error messages.
      * @return <code>null</code> if the <var>directory</var> is fully accessible and an error message describing the
      *         problem with the <var>directory</var> otherwise.
      */
@@ -434,20 +437,115 @@ public final class FileUtilities
             });
     }
 
-    /** Canonifies given relative path. */
-    public final static String canonifyRelativePath(final String relativePath)
+    /**
+     * Removes given <var>prefix</var> from given <var>file</var> and returns a new <code>File</code>.
+     * <p>
+     * Returns given <var>file</var> if prefix is <i>empty</i> or could not be found in the file name.
+     * </p>
+     * 
+     * @param file can not be <code>null</code>.
+     * @param prefix prefix that should be removed from the file name. Can be <code>null</code>.
+     */
+    public final static File removePrefixFromFileName(File file, String prefix)
     {
-        if (relativePath == null)
+        assert file != null;
+        String name = file.getName();
+        if (StringUtils.isEmpty(prefix))
         {
-            return null;
+            return file;
         }
-        String canonifiedPath = FilenameUtils.separatorsToUnix(relativePath);
-        if (canonifiedPath.startsWith("/"))
+        if (name.indexOf(prefix) < 0)
+        {
+            return file;
+        }
+        return new File(file.getParent(), name.substring(prefix.length()));
+    }
+
+    /** A <i>Java</i> pattern matching one or more digits. */
+    private final static Pattern ONE_OR_MORE_DIGITS = Pattern.compile("(\\d+)");
+
+    public final static File createNextNumberedFile(File path, String defaultFileName)
+    {
+        return createNextNumberedFile(path, null, defaultFileName);
+    }
+
+    /**
+     * Creates the next numbered file.
+     * <p>
+     * If the new suggested file already exists, then this method is called recursively.
+     * </p>
+     * 
+     * @param defaultFileName the default name for the new file if the digit pattern could not be found (probably the
+     *            starting file).
+     * @param regex pattern to find out the counter. If <code>null</code> then {@link #ONE_OR_MORE_DIGITS}} will be
+     *            taken. The given <var>regex</var> must contain <code>(\\d+)</code>.
+     */
+    public final static File createNextNumberedFile(File path, Pattern regex, String defaultFileName)
+    {
+        assert path != null;
+        final Pattern pattern;
+        if (regex == null)
         {
-            return canonifiedPath.substring(1);
+            pattern = ONE_OR_MORE_DIGITS;
         } else
         {
-            return canonifiedPath;
+            pattern = regex;
+        }
+        assert pattern.pattern().indexOf("(\\d+)") > -1;
+
+        String pathName = path.getName();
+        final Matcher matcher = pattern.matcher(pathName);
+        boolean found = matcher.find();
+        if (found == false)
+        {
+            if (StringUtils.isEmpty(defaultFileName) == false)
+            {
+                return new File(path.getParent(), defaultFileName);
+            }
+            return path;
+        }
+        StringBuilder builder = new StringBuilder();
+        int nextStart = 0;
+        while (found)
+        {
+            String group = matcher.group(1);
+            final int newNumber = Integer.parseInt(group) + 1;
+            builder.append(pathName.substring(nextStart, matcher.start(1))).append(newNumber);
+            nextStart = matcher.end(1);
+            found = matcher.find();
+        }
+        builder.append(pathName.substring(nextStart));
+        File newFile = new File(path.getParent(), builder.toString());
+        if (newFile.exists())
+        {
+            return createNextNumberedFile(newFile, pattern, defaultFileName);
+        }
+        return newFile;
+    }
+
+    /**
+     * For given <var>root</var> and <var>file</var> extracts the relative <code>File</code>.
+     * <p>
+     * If given <var>file</var> does not contain given <var>root</var> path in its absolute path, then returns
+     * <code>null</code> (as the relative file could not be determined).
+     * </p>
+     */
+    public final static File getRelativeFile(File root, File file)
+    {
+        assert file != null;
+        if (root == null)
+        {
+            return file;
+        }
+        String absolutePath = root.getAbsolutePath();
+        final String strRoot = absolutePath + File.separator;
+        final String absoluteFile = file.getAbsolutePath();
+        if (absoluteFile.startsWith(strRoot))
+        {
+            return new File(absoluteFile.substring(strRoot.length()));
+        } else
+        {
+            return null;
         }
     }
 }
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/FileUtilitiesTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/FileUtilitiesTest.java
index 4288ea6f07d278fd3c3344e116bf9aff7bd73f63..a9cb1138c0ecbe8a68c3df85a432b23506fb67a0 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/FileUtilitiesTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/FileUtilitiesTest.java
@@ -16,17 +16,23 @@
 
 package ch.systemsx.cisd.common.utilities;
 
-import static org.testng.AssertJUnit.*;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNull;
+import static org.testng.AssertJUnit.fail;
 
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.List;
+import java.util.regex.Pattern;
 
+import org.apache.commons.io.FilenameUtils;
 import org.testng.annotations.BeforeSuite;
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.common.Constants;
 import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.common.logging.LogInitializer;
 
@@ -122,8 +128,7 @@ public class FileUtilitiesTest
     @Test
     public void testLoadToStringMissingResource() throws Exception
     {
-        final String thisFile =
-                FileUtilities.loadToString(getClass(), "/some/missing/resource");
+        final String thisFile = FileUtilities.loadToString(getClass(), "/some/missing/resource");
         assert thisFile == null;
     }
 
@@ -144,12 +149,78 @@ public class FileUtilitiesTest
         assert file.delete();
         assertEquals(Arrays.asList("Hello", "World!"), text);
     }
-    
-    public final void testCanonifyRelativePath() {
-        assertNull(FileUtilities.canonifyRelativePath(null));
-        String relativePath = "/ch/systemsx/cisd/common/utilities/FileUtilitiesTest.class";
-        assertEquals("ch/systemsx/cisd/common/utilities/FileUtilitiesTest.class", FileUtilities.canonifyRelativePath(relativePath));
-        relativePath = "ch\\systemsx\\cisd\\common\\utilities\\FileUtilitiesTest.class";
-        assertEquals("ch/systemsx/cisd/common/utilities/FileUtilitiesTest.class", FileUtilities.canonifyRelativePath(relativePath));
+
+    @Test
+    public final void testRemovePrefixFromFileName()
+    {
+        File file = new File("/tmp/dir/x.txt");
+        try
+        {
+            FileUtilities.removePrefixFromFileName(null, Constants.IS_FINISHED_PREFIX);
+            fail("Given file can not be null.");
+        } catch (AssertionError e)
+        {
+            // Nothing to do here
+        }
+        assertEquals(file, FileUtilities.removePrefixFromFileName(file, null));
+        assertEquals(file, FileUtilities.removePrefixFromFileName(file, Constants.IS_FINISHED_PREFIX));
+        file = new File("/tmp/dir/" + Constants.IS_FINISHED_PREFIX + "x.txt");
+        assertEquals("/tmp/dir/x.txt", FileUtilities.removePrefixFromFileName(file, Constants.IS_FINISHED_PREFIX)
+                .getPath());
+    }
+
+    @Test
+    public final void testCreateNextNumberedFile()
+    {
+        File file = new File(workingDirectory, "abc_[12]");
+        assert file.exists() == false;
+        Pattern pattern = Pattern.compile("_\\[(\\d+)\\]");
+        File newFile = FileUtilities.createNextNumberedFile(file, pattern, null);
+        assertEquals(FilenameUtils.getName(new File(workingDirectory, "abc_[13]").getPath()), FilenameUtils
+                .getName(newFile.getPath()));
+        file = new File(workingDirectory, "abc");
+        newFile = FileUtilities.createNextNumberedFile(file, pattern, null);
+        assertEquals(FilenameUtils.getName(new File(workingDirectory, "abc").getPath()), FilenameUtils.getName(newFile
+                .getPath()));
+        try
+        {
+            FileUtilities.createNextNumberedFile(null, pattern, null);
+            fail("Null value for file not allowed.");
+        } catch (AssertionError e)
+        {
+            // Nothing to do here
+        }
+        newFile = FileUtilities.createNextNumberedFile(file, pattern, "abc_[1]");
+        assertEquals(FilenameUtils.getName(new File(workingDirectory, "abc_[1]").getPath()), FilenameUtils
+                .getName(newFile.getPath()));
+        file = new File(workingDirectory, "a0bc1");
+        newFile = FileUtilities.createNextNumberedFile(file, null);
+        assertEquals(FilenameUtils.getName(new File(workingDirectory, "a1bc2").getPath()), FilenameUtils
+                .getName(newFile.getPath()));
+    }
+
+    @Test
+    public final void testGetRelativeFile()
+    {
+        try
+        {
+            FileUtilities.getRelativeFile(null, null);
+            fail("Given file can not be null.");
+        } catch (AssertionError e)
+        {
+            // Nothing to do here
+        }
+        File file = new File(workingDirectory, "hello");
+        assertEquals(workingDirectory.getAbsolutePath() + File.separator + "hello", file.getAbsolutePath());
+        assertEquals(file, FileUtilities.getRelativeFile(null, file));
+        assertEquals(file, FileUtilities.getRelativeFile(new File(""), file));
+        File root = new File("/temp");
+        assertEquals("/temp", root.getAbsolutePath());
+        File relativeFile = FileUtilities.getRelativeFile(root, file);
+        assertNull(relativeFile);
+        root = workingDirectory;
+        relativeFile = FileUtilities.getRelativeFile(root, file);
+        assertFalse(relativeFile.isAbsolute());
+        assertEquals("hello", relativeFile.getPath());
     }
 }