diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+1.5.16
+
+* Add `cptreeL`
+
 1.5.15
 
 * Add `toLines`
diff --git a/src/Turtle/Bytes.hs b/src/Turtle/Bytes.hs
--- a/src/Turtle/Bytes.hs
+++ b/src/Turtle/Bytes.hs
@@ -49,6 +49,7 @@
 import Control.Monad.IO.Class (MonadIO(..))
 import Control.Monad.Managed (MonadManaged(..))
 import Data.ByteString (ByteString)
+import Data.Monoid
 import Data.Streaming.Zlib (Inflate, Popper, PopperRes(..), WindowBits(..))
 import Data.Text (Text)
 import Data.Text.Encoding (Decoding(..))
diff --git a/src/Turtle/Prelude.hs b/src/Turtle/Prelude.hs
--- a/src/Turtle/Prelude.hs
+++ b/src/Turtle/Prelude.hs
@@ -127,6 +127,7 @@
     , mktree
     , cp
     , cptree
+    , cptreeL
 #if !defined(mingw32_HOST_OS)
     , symlink
 #endif
@@ -1108,7 +1109,7 @@
 isNotSymbolicLink :: MonadIO io => FilePath -> io Bool
 isNotSymbolicLink = fmap (not . PosixCompat.isSymbolicLink) . lstat
 
--- | Copy a directory tree
+-- | Copy a directory tree and preserve symbolic links
 cptree :: MonadIO io => FilePath -> FilePath -> io ()
 cptree oldTree newTree = sh (do
     oldPath <- lsif isNotSymbolicLink oldTree
@@ -1139,6 +1140,18 @@
             cp oldPath newPath
         else do
             mktree newPath )
+
+-- | Copy a directory tree and dereference symbolic links
+cptreeL :: MonadIO io => FilePath -> FilePath -> io ()
+cptreeL oldTree newTree = sh (do
+    oldPath <- lstree oldTree
+    Just suffix <- return (Filesystem.stripPrefix (oldTree </> "") oldPath)
+    let newPath = newTree </> suffix
+    isFile <- testfile oldPath
+    if isFile
+        then mktree (Filesystem.directory newPath) >> cp oldPath newPath
+        else mktree newPath )
+
 
 -- | Remove a file
 rm :: MonadIO io => FilePath -> io ()
diff --git a/turtle.cabal b/turtle.cabal
--- a/turtle.cabal
+++ b/turtle.cabal
@@ -1,5 +1,5 @@
 Name: turtle
-Version: 1.5.15
+Version: 1.5.16
 Cabal-Version: >=1.10
 Build-Type: Simple
 License: BSD3
