diff --git a/System/Directory.hs b/System/Directory.hs
--- a/System/Directory.hs
+++ b/System/Directory.hs
@@ -570,33 +570,68 @@
     mapM_ removePathRecursive [path </> x | x <- cont]
     removeDirectory path
 
--- | @'removePathForcibly@ removes a file or directory at /path/ together with
--- its contents and subdirectories. Symbolic links are removed without
--- affecting their the targets. If the path does not exist, nothing happens.
+-- | Removes a file or directory at /path/ together with its contents and
+-- subdirectories. Symbolic links are removed without affecting their
+-- targets. If the path does not exist, nothing happens.
 --
 -- Unlike other removal functions, this function will also attempt to delete
 -- files marked as read-only or otherwise made unremovable due to permissions.
 -- As a result, if the removal is incomplete, the permissions or attributes on
 -- the remaining files may be altered.
+--
+-- If an entry within the directory vanishes while @removePathForcibly@ is
+-- running, it is silently ignored.
+--
+-- If an exception occurs while removing an entry, @removePathForcibly@ will
+-- still try to remove as many entries as it can before failing with an
+-- exception.  The first exception that it encountered is re-thrown.
+--
+-- @since 1.2.7.0
 removePathForcibly :: FilePath -> IO ()
 removePathForcibly path =
   (`ioeSetLocation` "removePathForcibly") `modifyIOError` do
     makeRemovable path `catchIOError` \ _ -> return ()
-    dirType <- tryIOErrorType isDoesNotExistError (getDirectoryType path)
-    case dirType of
-      Left _              -> return ()
-      Right NotDirectory  -> removeFile path
-      Right DirectoryLink -> removeDirectory path
-      Right Directory     -> do
-        mapM_ (removePathForcibly . (path </>)) =<< listDirectory path
-        removeDirectory path
+    ignoreDoesNotExistError $ do
+      dirType <- getDirectoryType path
+      case dirType of
+        NotDirectory  -> removeFile path
+        DirectoryLink -> removeDirectory path
+        Directory     -> do
+          names <- listDirectory path
+          sequenceWithIOErrors_ $
+            [ removePathForcibly (path </> name) | name <- names ] ++
+            [ removeDirectory path ]
   where
+
+    ignoreDoesNotExistError :: IO () -> IO ()
+    ignoreDoesNotExistError action = do
+      _ <- tryIOErrorType isDoesNotExistError action
+      return ()
+
+    makeRemovable :: FilePath -> IO ()
     makeRemovable p = do
       perms <- getPermissions p
       setPermissions path perms{ readable = True
                                , searchable = True
                                , writable = True }
 
+sequenceWithIOErrors_ :: [IO ()] -> IO ()
+sequenceWithIOErrors_ actions = go (Right ()) actions
+  where
+
+    go :: Either IOError () -> [IO ()] -> IO ()
+    go (Left e)   []       = ioError e
+    go (Right ()) []       = return ()
+    go s          (m : ms) = s `seq` do
+      r <- tryIOError m
+      go (thenEither s r) ms
+
+    -- equivalent to (*>) for Either, defined here to retain compatibility
+    -- with base prior to 4.3
+    thenEither :: Either b a -> Either b a -> Either b a
+    thenEither x@(Left _) _ = x
+    thenEither _          y = y
+
 {- |'removeFile' /file/ removes the directory entry for an existing file
 /file/, where /file/ is not itself a directory. The
 implementation may specify additional constraints which must be
@@ -633,7 +668,7 @@
 
 removeFile :: FilePath -> IO ()
 removeFile path =
-#if mingw32_HOST_OS
+#ifdef mingw32_HOST_OS
   Win32.deleteFile path
 #else
   Posix.removeLink path
@@ -814,6 +849,7 @@
 -- parent segments in the destination path is not a directory.
 -- @[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@
 --
+-- @since 1.2.7.0
 renamePath :: FilePath                  -- ^ Old path
            -> FilePath                  -- ^ New path
            -> IO ()
@@ -1395,6 +1431,8 @@
     action
 
 -- | Obtain the size of a file in bytes.
+--
+-- @since 1.2.7.0
 getFileSize :: FilePath -> IO Integer
 getFileSize path =
   (`ioeSetLocation` "getFileSize") `modifyIOError` do
@@ -1407,6 +1445,8 @@
 -- | Test whether the given path points to an existing filesystem object.  If
 -- the user lacks necessary permissions to search the parent directories, this
 -- function may return false even if the file does actually exist.
+--
+-- @since 1.2.7.0
 doesPathExist :: FilePath -> IO Bool
 doesPathExist path =
 #ifdef mingw32_HOST_OS
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,6 +1,12 @@
 Changelog for the [`directory`][1] package
 ==========================================
 
+## 1.2.7.1 (November 2016)
+
+  * Don't abort `removePathForcibly` if files or directories go missing.
+    In addition, keep going even if an exception occurs.
+    ([#60](https://github.com/haskell/directory/issues/60))
+
 ## 1.2.7.0 (August 2016)
 
   * Remove deprecated C bits.  This means `HsDirectory.h` and its functions
@@ -41,7 +47,7 @@
 
   * Add `findFileWith`
 
-  * Add `copyFileWithAttrs`, which copies additional metadata
+  * Add `copyFileWithMetadata`, which copies additional metadata
     ([#40](https://github.com/haskell/directory/issues/40))
 
   * Improve error message of `removeDirectoryRecursive` when used on a
diff --git a/directory.cabal b/directory.cabal
--- a/directory.cabal
+++ b/directory.cabal
@@ -1,5 +1,5 @@
 name:           directory
-version:        1.2.7.0
+version:        1.2.7.1
 -- NOTE: Don't forget to update ./changelog.md
 license:        BSD3
 license-file:   LICENSE
@@ -52,11 +52,11 @@
     include-dirs: .
 
     build-depends:
-        base     >= 4.5 && < 4.10,
-        time     >= 1.4 && < 1.7,
+        base     >= 4.5 && < 4.11,
+        time     >= 1.4 && < 1.8,
         filepath >= 1.3 && < 1.5
     if os(windows)
-        build-depends: Win32 >= 2.2.2 && < 2.4
+        build-depends: Win32 >= 2.2.2 && < 2.5
     else
         build-depends: unix >= 2.5.1 && < 2.8
 
diff --git a/tests/TestUtils.hs b/tests/TestUtils.hs
--- a/tests/TestUtils.hs
+++ b/tests/TestUtils.hs
@@ -52,7 +52,7 @@
   permissions <- getPermissions path
   setPermissions path (modify permissions)
 
-#if mingw32_HOST_OS
+#ifdef mingw32_HOST_OS
 createSymbolicLink :: String -> String -> IO ()
 createSymbolicLink target link =
   (`ioeSetLocation` "createSymbolicLink") `modifyIOError` do
