diff --git a/miv.cabal b/miv.cabal
--- a/miv.cabal
+++ b/miv.cabal
@@ -1,5 +1,5 @@
 name:                   miv
-version:                0.4.2
+version:                0.4.3
 author:                 itchyny <https://github.com/itchyny>
 maintainer:             itchyny <https://github.com/itchyny>
 license:                MIT
@@ -30,6 +30,7 @@
                       , process
                       , async
                       , concurrent-output
+                      , SafeSemaphore
                       , time
                       , directory
                       , hashable
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -4,11 +4,12 @@
 import Control.Applicative
 import Control.Concurrent (threadDelay, newEmptyMVar, forkIO, putMVar, takeMVar)
 import Control.Concurrent.Async
+import qualified Control.Concurrent.MSem as MSem
 import Control.Exception
 import Control.Monad (filterM, forM_, unless, void, when, guard)
 import qualified Control.Monad.Parallel as P
 import Data.Functor ((<&>))
-import Data.List (foldl', isPrefixOf, nub, sort, transpose, unfoldr, (\\))
+import Data.List (foldl', isPrefixOf, nub, sort)
 import Data.Maybe (listToMaybe, fromMaybe, isNothing)
 import Data.Text (Text, unlines, pack, unpack)
 import qualified Data.Text as T
@@ -226,8 +227,7 @@
   let count xs = if length xs > 1 then "s (" <> show (length xs) <> ")" else ""
   time <- maximum <$> mapM' (lastUpdatePlugin dir) ps
   status <- fmap mconcat <$> displayConsoleRegions $
-    mapConcurrently (fmap mconcat . mapM (\p -> updateOnePlugin time dir update (specified p) p)) $
-      transpose $ takeWhile (not . null) $ unfoldr (Just . splitAt 16) ps
+    mapM' (\p -> updateOnePlugin time dir update (specified p) p) ps
   putStrLn $ (if null (failed status) then "Success" else "Error occured") <> " in " <> show update <> "."
   unless (null (installed status)) $ do
     putStrLn $ "Installed plugin" <> count (installed status) <> ": "
@@ -242,8 +242,8 @@
   gatherFtdetectScript setting
   generateHelpTags setting
 
-mapM' :: P.MonadParallel m => (a -> m b) -> [a] -> m [b]
-mapM' f = fmap mconcat . P.mapM (mapM f) . transpose . takeWhile (not . null) . unfoldr (Just . splitAt 32)
+mapM' :: (a -> IO b) -> [a] -> IO [b]
+mapM' f xs = MSem.new (16 :: Int) >>= \sem -> mapConcurrently (MSem.with sem . f) xs
 
 cleanAndCreateDirectory :: FilePath -> IO ()
 cleanAndCreateDirectory dir = do
@@ -371,8 +371,8 @@
   createPluginDirectory
   dir <- pluginDirectory
   createDirectoryIfMissing True dir
-  cnt <- getDirectoryContents dir
-  let paths = "." : ".." : "miv" : map (unpack . show) (plugins setting)
+  cnt <- listDirectory dir
+  let paths = "miv" : map (unpack . show) (plugins setting)
       delpath' = [ dir </> d | d <- cnt, d `notElem` paths ]
   deldir <- filterM doesDirectoryExist delpath'
   delfile <- filterM doesFileExist delpath'
@@ -441,7 +441,7 @@
     let path = rtpName plugin
     exists <- doesDirectoryExist (dir </> path </> "ftdetect")
     when exists $ do
-      files <- getDirectoryContents (dir </> path </> "ftdetect") <&> (\\ [".", ".."])
+      files <- listDirectory (dir </> path </> "ftdetect")
       forM_ files $ \file ->
         copyFile (dir </> path </> "ftdetect" </> file) (dir </> "miv" </> "ftdetect" </> file)
   putStrLn "Success in gathering ftdetect scripts."
