diff --git a/README b/README
--- a/README
+++ b/README
@@ -16,7 +16,7 @@
 
   runHaskTagsVim() {
           # use --etags instead of --ctags for emacs
-          hasktags --ignore-close-implementation --ctags `find . -type f -name \"*.*hs\"`; sort tags
+          hasktags --ignore-close-implementation --ctags .; sort tags
   }
 
 HOWTO (USING TAG FILES):
@@ -44,3 +44,12 @@
 In the past this tool was distributed with ghc. I forked and added some
 features.  hasktags itself was moved out of the ghc repository. Then I only
 verified that my fork finds at least as much tags as the one forked by Igloo.
+
+
+related work (list taken from announce of lushtags:
+  https://github.com/bitc/lushtags
+  http://hackage.haskell.org/package/hasktags
+  http://kingfisher.nfshost.com/sw/gasbag/
+  http://hackage.haskell.org/package/hothasktags
+  http://majutsushi.github.com/tagbar/
+and probably much more
diff --git a/hasktags.cabal b/hasktags.cabal
--- a/hasktags.cabal
+++ b/hasktags.cabal
@@ -1,5 +1,5 @@
 Name: hasktags
-Version: 0.68.1
+Version: 0.68.2
 Copyright: The University Court of the University of Glasgow
 License: BSD3
 License-File: LICENSE
@@ -20,4 +20,5 @@
 
 Executable hasktags
     Main-Is: hasktags.hs
-    Build-Depends: haskell98, base < 5, bytestring
+    -- < 6 because hasktags does not use special functions thus its unlikely to break
+    Build-Depends: base < 6, bytestring, directory, filepath
diff --git a/hasktags.hs b/hasktags.hs
--- a/hasktags.hs
+++ b/hasktags.hs
@@ -5,10 +5,13 @@
 import Data.Maybe
 import Control.Monad( when )
 
-import IO
+import System.IO
 import System.Environment
+import System.Directory (doesDirectoryExist, getDirectoryContents)
+import System.FilePath ((</>))
 import System.Console.GetOpt
 import System.Exit
+import Control.Monad
 --import Debug.Trace
 
 
@@ -61,15 +64,23 @@
 main = do
         progName <- getProgName
         args <- getArgs
-        let usageString = "Usage: " ++ progName ++ " [OPTION...] [files...]"
-        let (modes, filenames, errs) = getOpt Permute options args
+        let usageString = 
+                   "Usage: " ++ progName ++ " [OPTION...] [files or directories...]\n"
+                ++ "directories will be replaced by DIR/**/*.hs DIR/**/*.lhs\n"
+                ++ "Thus hasktags . tags all important files in the current directory"
+        let a@(modes, files_or_dirs, errs) = getOpt Permute options args
 
-        when (errs /= [] || elem Help modes || filenames == [])
+        filenames <- liftM (nub . concat) $ mapM (dirToFiles False) files_or_dirs
+
+        when (errs /= [] || elem Help modes || files_or_dirs == [])
              (do putStr $ unlines errs
                  putStr $ usageInfo usageString options
                  exitWith (ExitFailure 1))
 
-        let mode = getMode (filter ( `elem` [BothTags, CTags, ETags, Append] ) modes)
+        when (filenames == []) $ do
+          putStrLn "warning: no files found!"
+
+        let mode = getMode (filter ( `elem` [BothTags, CTags, ETags] ) modes)
             openFileMode = if elem Append modes
                            then AppendMode
                            else WriteMode
@@ -81,7 +92,7 @@
                  hClose ctagsfile)
 
         when (mode == ETags)
-             (do etagsfile <- openFile "TAGS" openFileMode
+             (do etagsfile <- getOutFile "TAGS" openFileMode modes
                  writeetagsfile etagsfile filedata
                  hClose etagsfile)
 
@@ -95,6 +106,18 @@
                  hClose etagsfile
                  hClose ctagsfile)
 
+dirToFiles :: Bool -> FilePath -> IO [ FilePath ]
+dirToFiles hsExtOnly p = do
+  isD <- doesDirectoryExist p
+  if isD then recurse p
+         else return $ if not hsExtOnly || ".hs" `isSuffixOf` p || ".lhs" `isSuffixOf` p then [p] else []
+  where recurse p = do
+            names <- liftM (filter ( (/= '.') . head ) ) $ getDirectoryContents p
+                                      -- skip . .. and hidden files (linux)  
+            liftM concat $ mapM (processFile . (p </>) ) names
+        processFile f = dirToFiles True f
+
+
 -- | getMode takes a list of modes and extract the mode with the
 --   highest precedence.  These are as follows: Both, CTags, ETags
 --   The default case is Both.
@@ -129,7 +152,7 @@
           , Option "b" ["both"]
             (NoArg BothTags) "generate both CTAGS and ETAGS"
           , Option "a" ["append"]
-            (NoArg Append) "append to existing CTAGS and/or ETAGS file(s)"
+            (NoArg Append) "append to existing CTAGS and/or ETAGS file(s). After this file will no longer be sorted!"
           , Option "" ["ignore-close-implementation"]
             (NoArg IgnoreCloseImpl) "ignores found implementation if its closer than 7 lines  - so you can jump to definition in one shot"
           , Option "o" ["output"]
@@ -211,7 +234,12 @@
     mapM_ (hPutStrLn ctagsfile . dumpthing extended) (sortThings things)
 
 sortThings :: [FoundThing] -> [FoundThing]
-sortThings = sortBy (\(FoundThing _ a _) (FoundThing _ b _) -> compare a b)
+sortThings = sortBy comp
+  where 
+        comp (FoundThing _ a (Pos f1 l1 _ _)) (FoundThing _ b (Pos f2 l2 _ _)) =
+            c (c (compare a b) $ (compare f1 f2)) (compare l1 l2)
+        c a b = if a == EQ then b else a
+
 
 getfoundthings :: FileData -> [FoundThing]
 getfoundthings (FileData _ things) = things
