diff --git a/Data/ByteString/ShellEscape.hs b/Data/ByteString/ShellEscape.hs
new file mode 100644
--- /dev/null
+++ b/Data/ByteString/ShellEscape.hs
@@ -0,0 +1,16 @@
+
+{-| Typed shell escaping for Bourne Shell and Bash.
+ -}
+
+module Data.ByteString.ShellEscape
+  ( Data.ByteString.ShellEscape.Escape.Escape(..)
+  , Data.ByteString.ShellEscape.Sh.Sh()
+  , Data.ByteString.ShellEscape.Sh.sh
+  , Data.ByteString.ShellEscape.Bash.Bash()
+  , Data.ByteString.ShellEscape.Bash.bash
+  ) where
+
+import Data.ByteString.ShellEscape.Escape
+import Data.ByteString.ShellEscape.Sh
+import Data.ByteString.ShellEscape.Bash
+
diff --git a/Data/ByteString/ShellEscape/Bash.hs b/Data/ByteString/ShellEscape/Bash.hs
new file mode 100644
--- /dev/null
+++ b/Data/ByteString/ShellEscape/Bash.hs
@@ -0,0 +1,78 @@
+
+module Data.ByteString.ShellEscape.Bash where
+
+import Data.Maybe
+import Data.Char
+import Text.Printf
+import Data.ByteString (ByteString)
+
+import qualified Data.Vector as Vector
+
+import Data.ByteString.ShellEscape.Escape
+import qualified Data.ByteString.ShellEscape.Put as Put
+import Data.ByteString.ShellEscape.EscapeVector
+
+{-| A Bash escaped 'ByteString'. The strings are wrapped in @$\'...\'@ if any
+    bytes within them must be escaped; otherwise, they are left as is.
+    Newlines and other control characters are represented as ANSI escape
+    sequences. High bytes are represented as hex codes. Thus Bash escaped
+    strings will always fit on one line and never contain non-ASCII bytes.
+ -}
+newtype Bash                 =  Bash (EscapeVector EscapingMode)
+ deriving (Eq, Ord, Show)
+
+{-| Construct a Bash escaped intermediate form.
+ -}
+bash                        ::  ByteString -> Bash
+bash                         =  escape
+
+instance Escape Bash where
+  escape                     =  Bash . escWith classify
+  unescape (Bash v)          =  stripEsc v
+  bytes (Bash v) | literal v =  stripEsc v
+                 | otherwise =  interpretEsc v renderANSI' end (begin, Literal)
+   where
+    literal                  =  isNothing . Vector.find ((/= Literal) . snd)
+    begin                    =  [      Put.putString "$'"]
+    end                      =  const (Put.putChar '\'')
+    renderANSI' _ (c, e)     =  (renderANSI c, e)
+
+
+{-| Bash escaping modes.
+ -}
+data EscapingMode            =  ANSIHex | ANSIBackslash | Literal | Quoted
+ deriving (Eq, Ord, Show)
+
+renderANSI c =
+  case classify c of
+    Literal                 ->  Put.putChar     c
+    Quoted                  ->  Put.putChar     c
+    ANSIHex                 ->  Put.putString $ hexify c
+    ANSIBackslash           ->  Put.putString $ backslashify c
+
+backslashify                ::  Char -> String
+backslashify c               =  (take 2 . drop 1 . show) c
+
+hexify                      ::  Char -> String
+hexify                       =  printf "\\x%02X" . ord
+
+classify                    ::  Char -> EscapingMode
+classify c | c <= '\ACK'     =  ANSIHex
+           | c <= '\r'       =  ANSIBackslash
+           | c <= '\US'      =  ANSIHex
+           | c <= '&'        =  Quoted
+           | c == '\''       =  ANSIBackslash
+           | c <= '+'        =  Quoted
+           | c <= '9'        =  Literal
+           | c <= '?'        =  Quoted
+           | c <= 'Z'        =  Literal
+           | c == '['        =  Quoted
+           | c == '\\'       =  ANSIBackslash
+           | c <= ']'        =  Quoted
+           | c == '_'        =  Literal
+           | c <= '`'        =  Quoted
+           | c <= 'z'        =  Literal
+           | c <= '~'        =  Quoted
+           | c == '\DEL'     =  ANSIHex
+           | otherwise       =  ANSIHex
+
diff --git a/Data/ByteString/ShellEscape/Escape.hs b/Data/ByteString/ShellEscape/Escape.hs
new file mode 100644
--- /dev/null
+++ b/Data/ByteString/ShellEscape/Escape.hs
@@ -0,0 +1,21 @@
+
+module Data.ByteString.ShellEscape.Escape where
+
+import Data.ByteString
+
+{-| A type class for objects that represent an intermediate state of
+    escaping.
+ -}
+class Escape t where
+  -- |    Transform a 'ByteString' into the escaped intermediate form.
+  escape                    ::  ByteString -> t
+  -- |    Recover the original 'ByteString'.
+  unescape                  ::  t -> ByteString
+  -- |    Yield the escaped 'ByteString'.
+  bytes                     ::  t -> ByteString
+
+instance Escape ByteString where
+  escape                     =  id
+  unescape                   =  id
+  bytes                      =  id
+
diff --git a/Data/ByteString/ShellEscape/EscapeVector.hs b/Data/ByteString/ShellEscape/EscapeVector.hs
new file mode 100644
--- /dev/null
+++ b/Data/ByteString/ShellEscape/EscapeVector.hs
@@ -0,0 +1,39 @@
+
+module Data.ByteString.ShellEscape.EscapeVector where
+
+import Data.ByteString.Char8 (ByteString)
+import qualified Data.ByteString.Char8 as ByteString
+
+import Data.Vector (Vector)
+import qualified Data.Vector as Vector
+import qualified Data.Vector.Mutable as Vector (new, write)
+
+import qualified Data.ByteString.ShellEscape.Put as Put
+
+
+type EscapeVector escapingMode = Vector (Char, escapingMode)
+
+escWith :: (Char -> escapingMode) -> ByteString -> EscapeVector escapingMode
+escWith cf b                 =  Vector.create $ do
+  v                         <-  Vector.new (ByteString.length b)
+  sequence_ . snd $ ByteString.foldl' (f v) (0, []) b
+  return v
+ where
+  f v (i, ops) c             =  (i + 1, Vector.write v i (c, cf c) : ops)
+
+
+stripEsc                    ::  Vector (Char, escapingMode) -> ByteString
+stripEsc v                   =  ByteString.unfoldr f . fst $ Vector.unzip v
+ where
+  f v | Vector.null v        =  Nothing
+      | otherwise            =  Just (Vector.unsafeHead v, Vector.unsafeTail v)
+
+interpretEsc v f finish init =  (eval . (finish lastMode :)) instructions
+ where
+  eval                       =  Put.runPut' . sequence_ . reverse
+  (instructions, lastMode)   =  Vector.foldl' f' init v
+   where
+    f' (list, mode) (c, e)   =  (put:list, mode')
+     where
+      (put, mode')           =  f mode (c, e)
+
diff --git a/Data/ByteString/ShellEscape/Put.hs b/Data/ByteString/ShellEscape/Put.hs
new file mode 100644
--- /dev/null
+++ b/Data/ByteString/ShellEscape/Put.hs
@@ -0,0 +1,24 @@
+
+module Data.ByteString.ShellEscape.Put
+  ( module Data.Binary.Put
+  , putChar
+  , putString
+  , runPut'
+  ) where
+
+import Prelude hiding (putChar)
+import Data.Binary.Put
+import Data.Char
+import Data.ByteString.Lazy
+import Data.ByteString
+import Data.ByteString.Char8
+
+putChar                     ::  Char -> Put
+putChar                      =  putWord8 . toEnum . fromEnum
+
+putString                   ::  String -> Put
+putString                    =  putByteString . Data.ByteString.Char8.pack
+
+runPut'                     ::  Put -> Data.ByteString.ByteString
+runPut' = Data.ByteString.concat . Data.ByteString.Lazy.toChunks . runPut 
+
diff --git a/Data/ByteString/ShellEscape/Sh.hs b/Data/ByteString/ShellEscape/Sh.hs
new file mode 100644
--- /dev/null
+++ b/Data/ByteString/ShellEscape/Sh.hs
@@ -0,0 +1,69 @@
+
+module Data.ByteString.ShellEscape.Sh where
+
+import Data.ByteString (ByteString)
+
+import Data.ByteString.ShellEscape.Escape
+import qualified Data.ByteString.ShellEscape.Put as Put
+import Data.ByteString.ShellEscape.EscapeVector
+
+
+{-| A Bourne Shell escaped 'ByteString'. An oddity of Bourne shell escaping is
+    the absence of escape codes for newline and other ASCII control
+    characters. These bytes are simply placed literally in single quotes; the
+    effect is that a Bourne Shell escaped string may cover several lines and
+    contain non-ASCII bytes. Runs of bytes that must be escaped are wrapped in
+    @\'...\'@; bytes that are acceptable as literals in Bourne Shell are left
+    as is.
+ -}
+newtype Sh                   =  Sh (EscapeVector EscapingMode)
+ deriving (Eq, Ord, Show)
+
+{-| Construct a Bourne Shell escaped intermediate form.
+ -}
+sh                          ::  ByteString -> Sh
+sh                           =  escape
+
+instance Escape Sh where
+  escape                     =  Sh . escWith classify
+  unescape (Sh v)            =  stripEsc v
+  bytes (Sh v)               =  interpretEsc v act finish ([], Literal)
+   where
+    finish Quote             =  Put.putChar '\''
+    finish Backslash         =  Put.putChar '\\'
+    finish Literal           =  return ()
+
+
+{-| Accept the present escaping mode and desired escaping mode and yield an
+    action and the resulting mode.
+ -}
+act :: EscapingMode -> (Char, EscapingMode) -> (Put.Put, EscapingMode)
+act Quote (c, Quote)         =  (Put.putChar c                 , Quote)
+act Quote (c, Literal)       =  (Put.putChar c                 , Quote)
+act Quote (c, Backslash)     =  (Put.putString ['\'', '\\', c] , Literal)
+act Backslash (c, Backslash) =  (Put.putChar c                 , Literal)
+act Backslash (c, Quote)     =  (Put.putString ['\\', '\'', c] , Quote)
+act Backslash (c, Literal)   =  (Put.putString ['\\', c]       , Literal)
+act Literal (c, Literal)     =  (Put.putChar c                 , Literal)
+act Literal (c, Backslash)   =  (Put.putString ['\\', c]       , Literal)
+act Literal (c, Quote)       =  (Put.putString ['\'', c]       , Quote)
+
+classify                    ::  Char -> EscapingMode
+classify c | c <= '&'        =  Quote           --  0x00..0x26
+           | c == '\''       =  Backslash       --  0x27
+           | c <= ','        =  Quote           --  0x28..0x2c
+           | c <= '9'        =  Literal         --  0x2d..0x39
+           | c <= '?'        =  Quote           --  0x3a..0x3f
+           | c <= 'Z'        =  Literal         --  0x40..0x5a
+           | c <= '^'        =  Quote           --  0x5b..0x5e
+           | c == '_'        =  Literal         --  0x5f
+           | c == '`'        =  Quote           --  0x60
+           | c <= 'z'        =  Literal         --  0x61..0x7a
+           | c <= '\DEL'     =  Quote           --  0x7b..0x7f
+           | otherwise       =  Quote           --  0x80..0xff
+
+{-| Bourne Shell escaping modes. 
+ -}
+data EscapingMode            =  Backslash | Literal | Quote
+ deriving (Eq, Ord, Show)
+
diff --git a/Text/ShellEscape.hs b/Text/ShellEscape.hs
--- a/Text/ShellEscape.hs
+++ b/Text/ShellEscape.hs
@@ -3,14 +3,14 @@
  -}
 
 module Text.ShellEscape
-  ( Text.ShellEscape.Escape.Escape(..)
-  , Text.ShellEscape.Sh.Sh()
-  , Text.ShellEscape.Sh.sh
-  , Text.ShellEscape.Bash.Bash()
-  , Text.ShellEscape.Bash.bash
+  ( Data.ByteString.ShellEscape.Escape.Escape(..)
+  , Data.ByteString.ShellEscape.Sh.Sh()
+  , Data.ByteString.ShellEscape.Sh.sh
+  , Data.ByteString.ShellEscape.Bash.Bash()
+  , Data.ByteString.ShellEscape.Bash.bash
   ) where
 
-import Text.ShellEscape.Escape
-import Text.ShellEscape.Sh
-import Text.ShellEscape.Bash
+import Data.ByteString.ShellEscape.Escape
+import Data.ByteString.ShellEscape.Sh
+import Data.ByteString.ShellEscape.Bash
 
diff --git a/Text/ShellEscape/Bash.hs b/Text/ShellEscape/Bash.hs
deleted file mode 100644
--- a/Text/ShellEscape/Bash.hs
+++ /dev/null
@@ -1,78 +0,0 @@
-
-module Text.ShellEscape.Bash where
-
-import Data.Maybe
-import Data.Char
-import Text.Printf
-import Data.ByteString (ByteString)
-
-import qualified Data.Vector as Vector
-
-import Text.ShellEscape.Escape
-import qualified Text.ShellEscape.Put as Put
-import Text.ShellEscape.EscapeVector
-
-{-| A Bash escaped 'ByteString'. The strings are wrapped in @$\'...\'@ if any
-    bytes within them must be escaped; otherwise, they are left as is.
-    Newlines and other control characters are represented as ANSI escape
-    sequences. High bytes are represented as hex codes. Thus Bash escaped
-    strings will always fit on one line and never contain non-ASCII bytes.
- -}
-newtype Bash                 =  Bash (EscapeVector EscapingMode)
- deriving (Eq, Ord, Show)
-
-{-| Construct a Bash escaped intermediate form.
- -}
-bash                        ::  ByteString -> Bash
-bash                         =  escape
-
-instance Escape Bash where
-  escape                     =  Bash . escWith classify
-  unescape (Bash v)          =  stripEsc v
-  bytes (Bash v) | literal v =  stripEsc v
-                 | otherwise =  interpretEsc v renderANSI' end (begin, Literal)
-   where
-    literal                  =  isNothing . Vector.find ((/= Literal) . snd)
-    begin                    =  [      Put.putString "$'"]
-    end                      =  const (Put.putChar '\'')
-    renderANSI' _ (c, e)     =  (renderANSI c, e)
-
-
-{-| Bash escaping modes.
- -}
-data EscapingMode            =  ANSIHex | ANSIBackslash | Literal | Quoted
- deriving (Eq, Ord, Show)
-
-renderANSI c =
-  case classify c of
-    Literal                 ->  Put.putChar     c
-    Quoted                  ->  Put.putChar     c
-    ANSIHex                 ->  Put.putString $ hexify c
-    ANSIBackslash           ->  Put.putString $ backslashify c
-
-backslashify                ::  Char -> String
-backslashify c               =  (take 2 . drop 1 . show) c
-
-hexify                      ::  Char -> String
-hexify                       =  printf "\\x%02X" . ord
-
-classify                    ::  Char -> EscapingMode
-classify c | c <= '\ACK'     =  ANSIHex
-           | c <= '\r'       =  ANSIBackslash
-           | c <= '\US'      =  ANSIHex
-           | c <= '&'        =  Quoted
-           | c == '\''       =  ANSIBackslash
-           | c <= '+'        =  Quoted
-           | c <= '9'        =  Literal
-           | c <= '?'        =  Quoted
-           | c <= 'Z'        =  Literal
-           | c == '['        =  Quoted
-           | c == '\\'       =  ANSIBackslash
-           | c <= ']'        =  Quoted
-           | c == '_'        =  Literal
-           | c <= '`'        =  Quoted
-           | c <= 'z'        =  Literal
-           | c <= '~'        =  Quoted
-           | c == '\DEL'     =  ANSIHex
-           | otherwise       =  ANSIHex
-
diff --git a/Text/ShellEscape/Escape.hs b/Text/ShellEscape/Escape.hs
deleted file mode 100644
--- a/Text/ShellEscape/Escape.hs
+++ /dev/null
@@ -1,21 +0,0 @@
-
-module Text.ShellEscape.Escape where
-
-import Data.ByteString
-
-{-| A type class for objects that represent an intermediate state of
-    escaping.
- -}
-class Escape t where
-  -- |    Transform a 'ByteString' into the escaped intermediate form.
-  escape                    ::  ByteString -> t
-  -- |    Recover the original 'ByteString'.
-  unescape                  ::  t -> ByteString
-  -- |    Yield the escaped 'ByteString'.
-  bytes                     ::  t -> ByteString
-
-instance Escape ByteString where
-  escape                     =  id
-  unescape                   =  id
-  bytes                      =  id
-
diff --git a/Text/ShellEscape/EscapeVector.hs b/Text/ShellEscape/EscapeVector.hs
deleted file mode 100644
--- a/Text/ShellEscape/EscapeVector.hs
+++ /dev/null
@@ -1,39 +0,0 @@
-
-module Text.ShellEscape.EscapeVector where
-
-import Data.ByteString.Char8 (ByteString)
-import qualified Data.ByteString.Char8 as ByteString
-
-import Data.Vector (Vector)
-import qualified Data.Vector as Vector
-import qualified Data.Vector.Mutable as Vector (new, write)
-
-import qualified Text.ShellEscape.Put as Put
-
-
-type EscapeVector escapingMode = Vector (Char, escapingMode)
-
-escWith :: (Char -> escapingMode) -> ByteString -> EscapeVector escapingMode
-escWith cf b                 =  Vector.create $ do
-  v                         <-  Vector.new (ByteString.length b)
-  sequence_ . snd $ ByteString.foldl' (f v) (0, []) b
-  return v
- where
-  f v (i, ops) c             =  (i + 1, Vector.write v i (c, cf c) : ops)
-
-
-stripEsc                    ::  Vector (Char, escapingMode) -> ByteString
-stripEsc v                   =  ByteString.unfoldr f . fst $ Vector.unzip v
- where
-  f v | Vector.null v        =  Nothing
-      | otherwise            =  Just (Vector.unsafeHead v, Vector.unsafeTail v)
-
-interpretEsc v f finish init =  (eval . (finish lastMode :)) instructions
- where
-  eval                       =  Put.runPut' . sequence_ . reverse
-  (instructions, lastMode)   =  Vector.foldl' f' init v
-   where
-    f' (list, mode) (c, e)   =  (put:list, mode')
-     where
-      (put, mode')           =  f mode (c, e)
-
diff --git a/Text/ShellEscape/Put.hs b/Text/ShellEscape/Put.hs
deleted file mode 100644
--- a/Text/ShellEscape/Put.hs
+++ /dev/null
@@ -1,24 +0,0 @@
-
-module Text.ShellEscape.Put
-  ( module Data.Binary.Put
-  , putChar
-  , putString
-  , runPut'
-  ) where
-
-import Prelude hiding (putChar)
-import Data.Binary.Put
-import Data.Char
-import Data.ByteString.Lazy
-import Data.ByteString
-import Data.ByteString.Char8
-
-putChar                     ::  Char -> Put
-putChar                      =  putWord8 . toEnum . fromEnum
-
-putString                   ::  String -> Put
-putString                    =  putByteString . Data.ByteString.Char8.pack
-
-runPut'                     ::  Put -> Data.ByteString.ByteString
-runPut' = Data.ByteString.concat . Data.ByteString.Lazy.toChunks . runPut 
-
diff --git a/Text/ShellEscape/Sh.hs b/Text/ShellEscape/Sh.hs
deleted file mode 100644
--- a/Text/ShellEscape/Sh.hs
+++ /dev/null
@@ -1,69 +0,0 @@
-
-module Text.ShellEscape.Sh where
-
-import Data.ByteString (ByteString)
-
-import Text.ShellEscape.Escape
-import qualified Text.ShellEscape.Put as Put
-import Text.ShellEscape.EscapeVector
-
-
-{-| A Bourne Shell escaped 'ByteString'. An oddity of Bourne shell escaping is
-    the absence of escape codes for newline and other ASCII control
-    characters. These bytes are simply placed literally in single quotes; the
-    effect is that a Bourne Shell escaped string may cover several lines and
-    contain non-ASCII bytes. Runs of bytes that must be escaped are wrapped in
-    @\'...\'@; bytes that are acceptable as literals in Bourne Shell are left
-    as is.
- -}
-newtype Sh                   =  Sh (EscapeVector EscapingMode)
- deriving (Eq, Ord, Show)
-
-{-| Construct a Bourne Shell escaped intermediate form.
- -}
-sh                          ::  ByteString -> Sh
-sh                           =  escape
-
-instance Escape Sh where
-  escape                     =  Sh . escWith classify
-  unescape (Sh v)            =  stripEsc v
-  bytes (Sh v)               =  interpretEsc v act finish ([], Literal)
-   where
-    finish Quote             =  Put.putChar '\''
-    finish Backslash         =  Put.putChar '\\'
-    finish Literal           =  return ()
-
-
-{-| Accept the present escaping mode and desired escaping mode and yield an
-    action and the resulting mode.
- -}
-act :: EscapingMode -> (Char, EscapingMode) -> (Put.Put, EscapingMode)
-act Quote (c, Quote)         =  (Put.putChar c                 , Quote)
-act Quote (c, Literal)       =  (Put.putChar c                 , Quote)
-act Quote (c, Backslash)     =  (Put.putString ['\'', '\\', c] , Literal)
-act Backslash (c, Backslash) =  (Put.putChar c                 , Literal)
-act Backslash (c, Quote)     =  (Put.putString ['\\', '\'', c] , Quote)
-act Backslash (c, Literal)   =  (Put.putString ['\\', c]       , Literal)
-act Literal (c, Literal)     =  (Put.putChar c                 , Literal)
-act Literal (c, Backslash)   =  (Put.putString ['\\', c]       , Literal)
-act Literal (c, Quote)       =  (Put.putString ['\'', c]       , Quote)
-
-classify                    ::  Char -> EscapingMode
-classify c | c <= '&'        =  Quote           --  0x00..0x26
-           | c == '\''       =  Backslash       --  0x27
-           | c <= ','        =  Quote           --  0x28..0x2c
-           | c <= '9'        =  Literal         --  0x2d..0x39
-           | c <= '?'        =  Quote           --  0x3a..0x3f
-           | c <= 'Z'        =  Literal         --  0x40..0x5a
-           | c <= '^'        =  Quote           --  0x5b..0x5e
-           | c == '_'        =  Literal         --  0x5f
-           | c == '`'        =  Quote           --  0x60
-           | c <= 'z'        =  Literal         --  0x61..0x7a
-           | c <= '\DEL'     =  Quote           --  0x7b..0x7f
-           | otherwise       =  Quote           --  0x80..0xff
-
-{-| Bourne Shell escaping modes. 
- -}
-data EscapingMode            =  Backslash | Literal | Quote
- deriving (Eq, Ord, Show)
-
diff --git a/bench/Bench.hs b/bench/Bench.hs
--- a/bench/Bench.hs
+++ b/bench/Bench.hs
@@ -6,7 +6,7 @@
 
 import Criterion.Main
 
-import Text.ShellEscape
+import Data.ByteString.ShellEscape
 
 
 strings                     ::  [ByteString]
diff --git a/shell-escape.cabal b/shell-escape.cabal
--- a/shell-escape.cabal
+++ b/shell-escape.cabal
@@ -1,5 +1,5 @@
 name                          : shell-escape
-version                       : 0.1.2
+version                       : 0.2.0
 category                      : Text
 license                       : BSD3
 license-file                  : LICENSE
@@ -24,10 +24,11 @@
                               , containers
                               , vector >= 0.6.0.2
                               , bytestring >= 0.9
-  exposed-modules             : Text.ShellEscape
-  other-modules               : Text.ShellEscape.Escape
-                                Text.ShellEscape.EscapeVector
-                                Text.ShellEscape.Sh
-                                Text.ShellEscape.Bash
-                                Text.ShellEscape.Put
+  exposed-modules             : Data.ByteString.ShellEscape
+                                Text.ShellEscape
+  other-modules               : Data.ByteString.ShellEscape.Escape
+                                Data.ByteString.ShellEscape.EscapeVector
+                                Data.ByteString.ShellEscape.Sh
+                                Data.ByteString.ShellEscape.Bash
+                                Data.ByteString.ShellEscape.Put
 
diff --git a/test/Echo.hs b/test/Echo.hs
--- a/test/Echo.hs
+++ b/test/Echo.hs
@@ -18,7 +18,7 @@
 import Test.QuickCheck
 import Test.QuickCheck.Monadic
 
-import Text.ShellEscape hiding (sh, bash)
+import Data.ByteString.ShellEscape hiding (sh, bash)
 
 
 --  It is best to implement the echo test with `printf':
