diff --git a/ftp-client.cabal b/ftp-client.cabal
--- a/ftp-client.cabal
+++ b/ftp-client.cabal
@@ -1,5 +1,5 @@
 name: ftp-client
-version: 0.4.0.0
+version: 0.4.0.1
 cabal-version: >=1.10
 build-type: Simple
 license: PublicDomain
@@ -28,7 +28,8 @@
         attoparsec >=0.10 && <0.14,
         connection ==0.2.*,
         transformers >=0.5.2.0 && <0.6,
-        exceptions >=0.8.3 && <0.9
+        exceptions >=0.8.3 && <0.9,
+        containers >=0.5.7.1 && <0.6
     default-language: Haskell2010
     default-extensions: OverloadedStrings
     hs-source-dirs: src
@@ -38,7 +39,7 @@
     main-is: Spec.hs
     build-depends:
         base >=4.9.1.0 && <4.10,
-        ftp-client >=0.4.0.0 && <0.5
+        ftp-client >=0.4.0.1 && <0.5
     default-language: Haskell2010
     hs-source-dirs: test
     ghc-options: -threaded -rtsopts -with-rtsopts=-N
diff --git a/src/Network/FTP/Client.hs b/src/Network/FTP/Client.hs
--- a/src/Network/FTP/Client.hs
+++ b/src/Network/FTP/Client.hs
@@ -25,10 +25,12 @@
     retr,
     list,
     stor,
+    mlsd,
     -- * Types
     FTPCommand(..),
     FTPResponse(..),
     ResponseStatus(..),
+    MlsdResponse(..),
     RTypeCode(..),
     PortActivity(..),
     ProtType(..),
@@ -44,7 +46,8 @@
     getMultiLineResp,
     sendCommandLine,
     createSendDataCommand,
-    createTLSSendDataCommand
+    createTLSSendDataCommand,
+    parseMlsdLine
 ) where
 
 import qualified Data.ByteString.Char8 as C
@@ -66,7 +69,12 @@
 import Data.ByteString.Lazy.Internal (defaultChunkSize)
 import Data.Functor ((<$>))
 import Control.Applicative ((<*>))
+import Data.Map.Strict (Map)
+import qualified Data.Map.Strict as Map
+import Control.Arrow
 
+import Debug.Trace
+
 debugging :: Bool
 debugging = False
 
@@ -144,6 +152,7 @@
     | Rmd String
     | Pbsz Int
     | Prot ProtType
+    | Mlsd String
     | Cwd String
     | Cdup
     | Ccc
@@ -184,6 +193,7 @@
 serializeCommand (Pbsz buf)   = "PBSZ " <> show buf
 serializeCommand (Prot P)     = "PROT P"
 serializeCommand (Prot C)     = "PROT C"
+serializeCommand (Mlsd path)  = "MLSD " <> path
 serializeCommand (Cwd dir)    = "CWD " <> dir
 serializeCommand Cdup         = "CDUP"
 serializeCommand Ccc          = "CCC"
@@ -409,7 +419,7 @@
 getAllLineResp :: (MonadIO m, MonadCatch m) => Handle -> m ByteString
 getAllLineResp h = getAllLineResp' h []
     where
-        getAllLineResp' h ret = (do
+        getAllLineResp' h ret = ( do
             line <- liftIO $ getLineResp h
             getAllLineResp' h (ret <> [line]))
                 `M.catchIOError` (\_ -> return $ C.intercalate "\n" ret)
@@ -418,7 +428,7 @@
 recvAll :: (MonadIO m, MonadCatch m) => Handle -> m ByteString
 recvAll h = recvAll' ""
     where
-        recvAll' bs = (do
+        recvAll' bs = ( do
             chunk <- liftIO $ recv h defaultChunkSize
             recvAll' $ bs <> chunk)
                 `M.catchIOError` (\_ -> return bs)
@@ -638,7 +648,7 @@
 retr h path = withDataCommandSecurity h Passive [RType TI, Retr path] recvAll
 
 list :: (MonadIO m, MonadMask m) => Handle -> [String] -> m ByteString
-list h args = withDataCommandSecurity h Passive [RType TA, List args] recvAll
+list h args = withDataCommandSecurity h Passive [RType TA, List args] getAllLineResp
 
 stor
     :: (MonadIO m, MonadMask m)
@@ -650,3 +660,37 @@
 stor h loc dat rtype =
     withDataCommandSecurity h Passive [RType rtype, Stor loc]
         $ sendType rtype dat
+
+data MlsdResponse = MlsdResponse {
+    mrFilename :: String,
+    mrFacts :: Map String String
+} deriving (Show)
+
+splitApart :: Char -> ByteString -> (ByteString, ByteString)
+splitApart on s =
+    let (x0, x1) = C.break (== on) s
+    in (x0, C.drop 1 x1)
+
+parseMlsdLine :: ByteString -> MlsdResponse
+parseMlsdLine line =
+    let (factLine, filename) = splitApart ' ' line
+        bFacts = splitApart '=' <$> C.split ';' factLine
+        facts
+            = Map.fromList
+            $ filter (not . null . fst)
+            $ join (***) C.unpack <$> bFacts
+    in MlsdResponse (C.unpack filename) facts
+
+getMlsdResponse :: (MonadIO m, MonadCatch m) => Handle -> m [MlsdResponse]
+getMlsdResponse h = getMlsdResponse' h []
+    where
+        getMlsdResponse' h ret = ( do
+            line <- liftIO $ getLineResp h
+            getMlsdResponse' h $
+                if C.null line
+                    then ret
+                    else (parseMlsdLine line):ret
+            ) `M.catchIOError` (\_ -> return ret)
+
+mlsd :: (MonadIO m, MonadMask m) => Handle -> String -> m [MlsdResponse]
+mlsd h path = withDataCommandSecurity h Passive [RType TA, Mlsd path] getMlsdResponse
