diff --git a/Control/Shell/Directory.hs b/Control/Shell/Directory.hs
--- a/Control/Shell/Directory.hs
+++ b/Control/Shell/Directory.hs
@@ -101,7 +101,7 @@
       fromdirs <- filterM (\fl -> isDirectory (dir' </> fl)) files
       forM_ fromdirs $ \d -> go dir (subdir </> d)
 
--- | List the contents of a directory, sans '.' and '..'.
+-- | List the contents of a directory, sans @.@ and @..@.
 ls :: FilePath -> Shell [FilePath]
 ls dir = do
   e <- getEnv
diff --git a/Control/Shell/File.hs b/Control/Shell/File.hs
--- a/Control/Shell/File.hs
+++ b/Control/Shell/File.hs
@@ -28,11 +28,20 @@
   e <- getEnv
   unsafeLiftIO $ Dir.removeFile (absPath e dir)
 
--- | Rename a file.
+-- | Rename a file or directory. If the target is a directory, then the source
+--   will be moved into that directory.
 mv :: FilePath -> FilePath -> Shell ()
 mv from to = do
   e <- getEnv
-  unsafeLiftIO $ Dir.renameFile (absPath e from) (absPath e to)
+  unsafeLiftIO $ do
+    targetIsDir <- Dir.doesDirectoryExist (absPath e to)
+    sourceIsDir <- Dir.doesDirectoryExist (absPath e from)
+    if sourceIsDir
+      then Dir.renameDirectory (absPath e from) (targetPath targetIsDir e)
+      else Dir.renameFile (absPath e from) (targetPath targetIsDir e)
+  where
+    targetPath True e  = absPath e to </> takeBaseName from
+    targetPath False e = absPath e to
 
 -- | Copy a file. Fails if the source is a directory. If the target is a
 --   directory, the source file is copied into that directory using its current
diff --git a/Control/Shell/Internal.hs b/Control/Shell/Internal.hs
--- a/Control/Shell/Internal.hs
+++ b/Control/Shell/Internal.hs
@@ -90,13 +90,15 @@
 runSh _ (Lift m) = do
   Ex.catch (Right <$> m)
            (\(Ex.SomeException e) -> pure $ Left (Failure (show e)))
-runSh env (Pipe p) = do
+runSh env (Pipe p) = flip Ex.catch except $ do
   ((stepenv, step) : steps) <- mkEnvs env p
   ma <- waitPids =<< mapM (uncurry (runStep True)) steps
   mb <- waitPids . (:[]) =<< runStep False stepenv step
   case ma >> mb of
     Just err -> pure $ Left err
     _        -> pure $ Right ()
+  where
+    except = \(Ex.SomeException e) -> pure $ Left (Failure (show e))
 runSh _ Done = do
   return $ Left Success
 runSh env (Bind m f) = do
diff --git a/Control/Shell/Temp.hs b/Control/Shell/Temp.hs
--- a/Control/Shell/Temp.hs
+++ b/Control/Shell/Temp.hs
@@ -4,6 +4,8 @@
   , withTempFile, withCustomTempFile
   ) where
 import Control.Shell.Base
+import Control.Shell.Directory (rmdir, isDirectory)
+import Control.Shell.Control (when)
 import qualified System.IO.Temp as Temp
 import qualified System.IO as IO
 
@@ -16,7 +18,7 @@
   unsafeLiftIO $ do
     oldenv <- setShellEnv env
     Temp.withSystemTempDirectory "shellmate" $ \fp -> do
-      setShellEnv oldenv
+      _ <- setShellEnv oldenv
       runSh env $ do
         releaseEnvLock
         act fp
@@ -30,10 +32,12 @@
   unsafeLiftIO $ do
     oldenv <- setShellEnv env
     Temp.withTempDirectory dir "shellmate" $ \fp -> do
-      setShellEnv oldenv
+      _ <- setShellEnv oldenv
       runSh env $ do
         releaseEnvLock
-        act fp
+        x <- act fp
+        when (isDirectory fp) $ rmdir fp
+        return x
 
 -- | Create a temp file in the standard system temp directory, do something
 --   with it, then remove it.
@@ -44,7 +48,7 @@
   unsafeLiftIO $ do
     oldenv <- setShellEnv env
     Temp.withSystemTempFile "shellmate" $ \fp h -> do
-      setShellEnv oldenv
+      _ <- setShellEnv oldenv
       runSh env $ do
         releaseEnvLock
         unsafeLiftIO $ IO.hSetBinaryMode h (fm == BinaryMode)
@@ -59,7 +63,7 @@
   unsafeLiftIO $ do
     oldenv <- setShellEnv env
     Temp.withTempFile dir "shellmate" $ \fp h -> do
-      setShellEnv oldenv
+      _ <- setShellEnv oldenv
       runSh env $ do
         releaseEnvLock
         unsafeLiftIO $ IO.hSetBinaryMode h (fm == BinaryMode)
diff --git a/shellmate.cabal b/shellmate.cabal
--- a/shellmate.cabal
+++ b/shellmate.cabal
@@ -1,5 +1,5 @@
 name:                shellmate
-version:             0.3
+version:             0.3.1
 synopsis:            Simple interface for shell scripting in Haskell.
 description:         Aims to simplify development of cross-platform shell scripts and similar things.
 homepage:            https://github.com/valderman/shellmate
@@ -38,3 +38,5 @@
     temporary    >=1.1  && <1.3
   default-language:
     Haskell2010
+  ghc-options:
+    -Wall
