diff --git a/applications/test/fileName/Test-fileName.C b/applications/test/fileName/Test-fileName.C
index fb876727437b864cec08ab614c911342171be02f..37ad0c90390500aee9d9344181672ed68c4aece4 100644
--- a/applications/test/fileName/Test-fileName.C
+++ b/applications/test/fileName/Test-fileName.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -34,6 +34,7 @@ Description
 #include "IOobject.H"
 #include "IOstreams.H"
 #include "OSspecific.H"
+#include "POSIX.H"
 
 using namespace Foam;
 
@@ -99,6 +100,98 @@ int main()
 
     }
 
+
+    // Test some copying and deletion
+    {
+        const fileName dirA("dirA");
+        const fileName lnA("lnA");
+        const fileName lnB("lnB");
+        const fileName dirB("dirB");
+
+        Foam::rmDir(dirA);
+        Foam::rm(lnA);
+        Foam::rm(lnB);
+        Foam::rmDir(dirB);
+
+
+        Info<< "Creating directory " << dirA << endl;
+        Foam::mkDir(dirA);
+
+
+        const int oldPosix = POSIX::debug;
+        POSIX::debug = 1;
+
+
+        // Create link and test it
+        Info<< "Creating softlink " << lnA << endl;
+        Foam::ln(dirA, lnA);
+
+        fileName::Type lnAType = lnA.type(false);
+
+        if (lnAType != fileName::LINK)
+        {
+            FatalErrorIn("Test-fileName") << "Type of softlink " << lnA
+                << " should be " << fileName::LINK
+                << " but is " << lnAType << exit(FatalError);
+        }
+
+        fileName::Type dirAType = lnA.type(true);
+
+        if (dirAType != fileName::DIRECTORY)
+        {
+            FatalErrorIn("Test-fileName") << "Type of what softlink " << lnA
+                << " points to should be " << fileName::DIRECTORY
+                << " but is " << dirAType << exit(FatalError);
+        }
+
+        // Copy link only
+        {
+            Info<< "Copying (non-follow) softlink " << lnA << " to " << lnB
+                << endl;
+
+            Foam::cp(lnA, lnB, false);
+            if (lnB.type(false) != fileName::LINK)
+            {
+                FatalErrorIn("Test-fileName") << "Type of softlink " << lnB
+                    << " should be " << fileName::LINK
+                    << " but is " << lnB.type(false) << exit(FatalError);
+            }
+            if (lnB.type(true) != fileName::DIRECTORY)
+            {
+                FatalErrorIn("Test-fileName") << "Type of softlink " << lnB
+                    << " should be " << fileName::DIRECTORY
+                    << " but is " << lnB.type(true) << exit(FatalError);
+            }
+
+            // Delete
+            Foam::rm(lnB);
+        }
+
+        // Copy contents of link
+        {
+            Info<< "Copying (contents of) softlink " << lnA << " to " << lnB
+                << endl;
+
+            Foam::cp(lnA, lnB, true);
+            if (lnB.type(false) != fileName::DIRECTORY)
+            {
+                FatalErrorIn("Test-fileName") << "Type of softlink " << lnB
+                    << " should be " << fileName::DIRECTORY
+                    << " but is " << lnB.type(false) << exit(FatalError);
+            }
+
+            // Delete
+            Foam::rm(lnB);
+        }
+
+        POSIX::debug = oldPosix;
+
+        Foam::rmDir(dirA);
+        Foam::rm(lnA);
+    }
+
+
+
     // test findEtcFile
     Info<< "\n\nfindEtcFile tests:" << nl
         << " controlDict => " << findEtcFile("controlDict") << nl
diff --git a/src/OSspecific/POSIX/POSIX.C b/src/OSspecific/POSIX/POSIX.C
index 0b9a541d94083d0aa63f2b5641b300ae5ef64762..41645bf73674da8338b1ee6ce696629f786b8c63 100644
--- a/src/OSspecific/POSIX/POSIX.C
+++ b/src/OSspecific/POSIX/POSIX.C
@@ -593,9 +593,9 @@ bool Foam::chMod(const fileName& name, const mode_t m)
 }
 
 
-mode_t Foam::mode(const fileName& name)
+mode_t Foam::mode(const fileName& name, const bool followLink)
 {
-    fileStat fileStatus(name);
+    fileStat fileStatus(name, followLink);
     if (fileStatus.isValid())
     {
         return fileStatus.status().st_mode;
@@ -607,14 +607,18 @@ mode_t Foam::mode(const fileName& name)
 }
 
 
-Foam::fileName::Type Foam::type(const fileName& name)
+Foam::fileName::Type Foam::type(const fileName& name, const bool followLink)
 {
-    mode_t m = mode(name);
+    mode_t m = mode(name, followLink);
 
     if (S_ISREG(m))
     {
         return fileName::FILE;
     }
+    else if (S_ISLNK(m))
+    {
+        return fileName::LINK;
+    }
     else if (S_ISDIR(m))
     {
         return fileName::DIRECTORY;
@@ -626,27 +630,39 @@ Foam::fileName::Type Foam::type(const fileName& name)
 }
 
 
-bool Foam::exists(const fileName& name, const bool checkGzip)
+bool Foam::exists
+(
+    const fileName& name,
+    const bool checkGzip,
+    const bool followLink
+)
 {
-    return mode(name) || isFile(name, checkGzip);
+    return mode(name, followLink) || isFile(name, checkGzip, followLink);
 }
 
 
-bool Foam::isDir(const fileName& name)
+bool Foam::isDir(const fileName& name, const bool followLink)
 {
-    return S_ISDIR(mode(name));
+    return S_ISDIR(mode(name, followLink));
 }
 
 
-bool Foam::isFile(const fileName& name, const bool checkGzip)
+bool Foam::isFile
+(
+    const fileName& name,
+    const bool checkGzip,
+    const bool followLink
+)
 {
-    return S_ISREG(mode(name)) || (checkGzip && S_ISREG(mode(name + ".gz")));
+    return
+        S_ISREG(mode(name, followLink))
+     || (checkGzip && S_ISREG(mode(name + ".gz", followLink)));
 }
 
 
-off_t Foam::fileSize(const fileName& name)
+off_t Foam::fileSize(const fileName& name, const bool followLink)
 {
-    fileStat fileStatus(name);
+    fileStat fileStatus(name, followLink);
     if (fileStatus.isValid())
     {
         return fileStatus.status().st_size;
@@ -658,9 +674,9 @@ off_t Foam::fileSize(const fileName& name)
 }
 
 
-time_t Foam::lastModified(const fileName& name)
+time_t Foam::lastModified(const fileName& name, const bool followLink)
 {
-    fileStat fileStatus(name);
+    fileStat fileStatus(name, followLink);
     if (fileStatus.isValid())
     {
         return fileStatus.status().st_mtime;
@@ -676,7 +692,8 @@ Foam::fileNameList Foam::readDir
 (
     const fileName& directory,
     const fileName::Type type,
-    const bool filtergz
+    const bool filtergz,
+    const bool followLink
 )
 {
     // Initial filename list size
@@ -717,10 +734,10 @@ Foam::fileNameList Foam::readDir
         {
             fileName fName(list->d_name);
 
-            // ignore files begining with ., i.e. '.', '..' and '.*'
+            // ignore files beginning with ., i.e. '.', '..' and '.*'
             if (fName.size() && fName[0] != '.')
             {
-                word fExt = fName.ext();
+                const word fExt = fName.ext();
 
                 if
                 (
@@ -736,7 +753,7 @@ Foam::fileNameList Foam::readDir
                     )
                 )
                 {
-                    if ((directory/fName).type() == type)
+                    if ((directory/fName).type(followLink) == type)
                     {
                         if (nEntries >= dirEntries.size())
                         {
@@ -766,7 +783,7 @@ Foam::fileNameList Foam::readDir
 }
 
 
-bool Foam::cp(const fileName& src, const fileName& dest)
+bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink)
 {
     // Make sure source exists.
     if (!exists(src))
@@ -777,7 +794,8 @@ bool Foam::cp(const fileName& src, const fileName& dest)
     fileName destFile(dest);
 
     // Check type of source file.
-    if (src.type() == fileName::FILE)
+    const fileName::Type srcType = src.type(followLink);
+    if (srcType == fileName::FILE)
     {
         // If dest is a directory, create the destination file name.
         if (destFile.type() == fileName::DIRECTORY)
@@ -817,7 +835,23 @@ bool Foam::cp(const fileName& src, const fileName& dest)
             return false;
         }
     }
-    else if (src.type() == fileName::DIRECTORY)
+    else if (srcType == fileName::LINK)
+    {
+        // If dest is a directory, create the destination file name.
+        if (destFile.type() == fileName::DIRECTORY)
+        {
+            destFile = destFile/src.name();
+        }
+
+        // Make sure the destination directory exists.
+        if (!isDir(destFile.path()) && !mkDir(destFile.path()))
+        {
+            return false;
+        }
+
+        ln(src, destFile);
+    }
+    else if (srcType == fileName::DIRECTORY)
     {
         // If dest is a directory, create the destination file name.
         if (destFile.type() == fileName::DIRECTORY)
@@ -832,7 +866,7 @@ bool Foam::cp(const fileName& src, const fileName& dest)
         }
 
         // Copy files
-        fileNameList contents = readDir(src, fileName::FILE, false);
+        fileNameList contents = readDir(src, fileName::FILE, false, followLink);
         forAll(contents, i)
         {
             if (POSIX::debug)
@@ -843,11 +877,17 @@ bool Foam::cp(const fileName& src, const fileName& dest)
             }
 
             // File to file.
-            cp(src/contents[i], destFile/contents[i]);
+            cp(src/contents[i], destFile/contents[i], followLink);
         }
 
         // Copy sub directories.
-        fileNameList subdirs = readDir(src, fileName::DIRECTORY);
+        fileNameList subdirs = readDir
+        (
+            src,
+            fileName::DIRECTORY,
+            false,
+            followLink
+        );
         forAll(subdirs, i)
         {
             if (POSIX::debug)
@@ -858,9 +898,13 @@ bool Foam::cp(const fileName& src, const fileName& dest)
             }
 
             // Dir to Dir.
-            cp(src/subdirs[i], destFile);
+            cp(src/subdirs[i], destFile, followLink);
         }
     }
+    else
+    {
+        return false;
+    }
 
     return true;
 }
@@ -903,7 +947,7 @@ bool Foam::ln(const fileName& src, const fileName& dst)
 }
 
 
-bool Foam::mv(const fileName& src, const fileName& dst)
+bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink)
 {
     if (POSIX::debug)
     {
@@ -914,7 +958,7 @@ bool Foam::mv(const fileName& src, const fileName& dst)
     if
     (
         dst.type() == fileName::DIRECTORY
-     && src.type() != fileName::DIRECTORY
+     && src.type(followLink) != fileName::DIRECTORY
     )
     {
         const fileName dstName(dst/src.name());
@@ -1016,7 +1060,7 @@ bool Foam::rmDir(const fileName& directory)
             {
                 fileName path = directory/fName;
 
-                if (path.type() == fileName::DIRECTORY)
+                if (path.type(false) == fileName::DIRECTORY)
                 {
                     if (!rmDir(path))
                     {
diff --git a/src/OSspecific/POSIX/fileStat.C b/src/OSspecific/POSIX/fileStat.C
index 9826983d642d8d09cc5035a35dee4c0ce9ec87bf..f40192f03bc4b4292641877e539dc03a4a50ce6b 100644
--- a/src/OSspecific/POSIX/fileStat.C
+++ b/src/OSspecific/POSIX/fileStat.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -29,6 +29,7 @@ License
 
 #include <signal.h>
 #include <unistd.h>
+#include <sys/sysmacros.h>
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
@@ -38,7 +39,12 @@ Foam::fileStat::fileStat()
 {}
 
 
-Foam::fileStat::fileStat(const fileName& fName, const unsigned int maxTime)
+Foam::fileStat::fileStat
+(
+    const fileName& fName,
+    const bool followLink,
+    const unsigned int maxTime
+)
 {
     // Work on volatile
     volatile bool locIsValid = false;
@@ -47,13 +53,13 @@ Foam::fileStat::fileStat(const fileName& fName, const unsigned int maxTime)
 
     if (!timedOut(myTimer))
     {
-        if (::stat(fName.c_str(), &status_) != 0)
+        if (followLink)
         {
-            locIsValid = false;
+            locIsValid = (::stat(fName.c_str(), &status_) == 0);
         }
         else
         {
-            locIsValid = true;
+            locIsValid = (::lstat(fName.c_str(), &status_) == 0);
         }
     }
 
diff --git a/src/OSspecific/POSIX/fileStat.H b/src/OSspecific/POSIX/fileStat.H
index fe16d20470b1ceb53795c39f8e44c0fc835c9992..634d0f59bd61dc8541135740bfc01a553da02389 100644
--- a/src/OSspecific/POSIX/fileStat.H
+++ b/src/OSspecific/POSIX/fileStat.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,7 +25,7 @@ Class
     Foam::fileStat
 
 Description
-    Wrapper for stat() system call.
+    Wrapper for stat() and lstat() system calls.
 
 Warning
     on Linux (an maybe on others) a stat() of an nfs mounted (remote)
@@ -79,8 +79,21 @@ public:
         //- Empty constructor
         fileStat();
 
-        //- Construct from components
-        fileStat(const fileName& fName, const unsigned int maxTime=0);
+        //- Construct from components.
+        // \param fName \n
+        // The file name or directory name to stat.
+        //
+        // \param followLink \n
+        // If it is a link, get the status of the source file/directory.
+        //
+        // \param maxTime \n
+        // The timeout value.
+        fileStat
+        (
+            const fileName& fName,
+            const bool followLink = true,
+            const unsigned int maxTime = 0
+        );
 
         //- Construct from Istream
         fileStat(Istream&);
@@ -96,7 +109,7 @@ public:
                 return status_;
             }
 
-            //- Did constructor fail
+            //- Was file-stat successful?
             bool isValid() const
             {
                 return isValid_;
diff --git a/src/OpenFOAM/include/OSspecific.H b/src/OpenFOAM/include/OSspecific.H
index d190f67045e2536e9b131f4a2e41ea292b310758..79a2417319b6cf5a71e04a179b4a10a9a2c88e49 100644
--- a/src/OpenFOAM/include/OSspecific.H
+++ b/src/OpenFOAM/include/OSspecific.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -132,44 +132,60 @@ bool mkDir(const fileName&, mode_t=0777);
 bool chMod(const fileName&, const mode_t);
 
 //- Return the file mode
-mode_t mode(const fileName&);
+mode_t mode(const fileName&, const bool followLink=true);
 
 //- Return the file type: DIRECTORY or FILE
-fileName::Type type(const fileName&);
+fileName::Type type(const fileName&, const bool followLink=true);
 
 //- Does the name exist (as DIRECTORY or FILE) in the file system?
 //  Optionally enable/disable check for gzip file.
-bool exists(const fileName&, const bool checkGzip=true);
+bool exists
+(
+    const fileName&,
+    const bool checkGzip=true,
+    const bool followLink=true
+);
 
 //- Does the name exist as a DIRECTORY in the file system?
-bool isDir(const fileName&);
+bool isDir(const fileName&, const bool followLink=true);
 
 //- Does the name exist as a FILE in the file system?
 //  Optionally enable/disable check for gzip file.
-bool isFile(const fileName&, const bool checkGzip=true);
+bool isFile
+(
+    const fileName&,
+    const bool checkGzip=true,
+    const bool followLink=true
+);
 
 //- Return size of file
-off_t fileSize(const fileName&);
+off_t fileSize(const fileName&, const bool followLink=true);
 
 //- Return time of last file modification
-time_t lastModified(const fileName&);
+time_t lastModified(const fileName&, const bool followLink=true);
 
 //- Read a directory and return the entries as a string list
 fileNameList readDir
 (
     const fileName&,
     const fileName::Type=fileName::FILE,
-    const bool filtergz=true
+    const bool filtergz=true,
+    const bool followLink=true
 );
 
 //- Copy, recursively if necessary, the source to the destination
-bool cp(const fileName& src, const fileName& dst);
+bool cp(const fileName& src, const fileName& dst, const bool followLink=true);
 
 //- Create a softlink. dst should not exist. Returns true if successful.
 bool ln(const fileName& src, const fileName& dst);
 
 //- Rename src to dst
-bool mv(const fileName& src, const fileName& dst);
+bool mv
+(
+    const fileName& src,
+    const fileName& dst,
+    const bool followLink=false
+);
 
 //- Rename to a corresponding backup file
 //  If the backup file already exists, attempt with "01" .. "99" suffix
diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.C b/src/OpenFOAM/primitives/strings/fileName/fileName.C
index becb5db393dafb6ae591721926d6614cc2048fc5..0dd888c737affb70f4d643f65194a26af20760bf 100644
--- a/src/OpenFOAM/primitives/strings/fileName/fileName.C
+++ b/src/OpenFOAM/primitives/strings/fileName/fileName.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -48,9 +48,9 @@ Foam::fileName::fileName(const wordList& lst)
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
-Foam::fileName::Type Foam::fileName::type() const
+Foam::fileName::Type Foam::fileName::type(const bool followLink) const
 {
-    return ::Foam::type(*this);
+    return ::Foam::type(*this, followLink);
 }
 
 
@@ -94,6 +94,7 @@ bool Foam::fileName::clean()
     (
         string::size_type src = nChar;
         src < maxLen;
+        /*nil*/
     )
     {
         char c = operator[](src++);
diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.H b/src/OpenFOAM/primitives/strings/fileName/fileName.H
index 288da061b87715a3fd4c5d652ff571d3467fa5ce..e45844eaeb7385b1aa77b137bac32da70c9d2404 100644
--- a/src/OpenFOAM/primitives/strings/fileName/fileName.H
+++ b/src/OpenFOAM/primitives/strings/fileName/fileName.H
@@ -154,8 +154,9 @@ public:
 
         // Interrogation
 
-            //- Return the file type: FILE, DIRECTORY or UNDEFINED
-            Type type() const;
+            //- Return the file type: FILE, DIRECTORY, UNDEFINED or
+            //  LINK (only if followLink=false)
+            Type type(const bool followLink = true) const;
 
             //- Return true if file name is absolute
             bool isAbsolute() const;