diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py
--- a/hgext/largefiles/lfcommands.py
+++ b/hgext/largefiles/lfcommands.py
@@ -530,24 +530,6 @@ def _updatelfile(repo, lfdirstate, lfile
         lfdirstate.drop(lfile)
     return ret
 
-def catlfile(repo, lfile, rev, filename):
-    hash = lfutil.readstandin(repo, lfile, rev)
-    if not lfutil.inusercache(repo.ui, hash):
-        store = basestore._openstore(repo)
-        success, missing = store.get([(lfile, hash)])
-        if len(success) != 1:
-            raise util.Abort(
-                _('largefile %s is not in cache and could not be downloaded')
-                    % lfile)
-    path = lfutil.usercachepath(repo.ui, hash)
-    fpout = cmdutil.makefileobj(repo, filename)
-    fpin = open(path, "rb")
-    for chunk in lfutil.blockstream(fpin):
-        fpout.write(chunk)
-    fpout.close()
-    fpin.close()
-    return 0
-
 # -- hg commands declarations ------------------------------------------------
 
 cmdtable = {
diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -19,6 +19,7 @@ from hgext import rebase
 
 import lfutil
 import lfcommands
+import basestore
 
 # -- Utility functions: commonly/repeatedly needed functionality ---------------
 
@@ -1155,13 +1156,37 @@ def overridecat(orig, ui, repo, file1, *
         notbad.add(lf)
         return origmatchfn(lf)
     m.matchfn = lfmatchfn
-    m.bad = lambda f, msg: f not in notbad
+    origbadfn = m.bad
+    def lfbadfn(f, msg):
+        if not f in notbad:
+            return origbadfn(f, msg)
+    m.bad = lfbadfn
     for f in ctx.walk(m):
+        fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
+                                 pathname=f)
         lf = lfutil.splitstandin(f)
         if lf is None:
-            err = orig(ui, repo, f, **opts)
+            # duplicating unreachable code from commands.cat
+            data = ctx[f].data()
+            if opts.get('decode'):
+                data = repo.wwritedata(f, data)
+            fp.write(data)
         else:
-            err = lfcommands.catlfile(repo, lf, ctx.rev(), opts.get('output'))
+            hash = lfutil.readstandin(repo, lf, ctx.rev())
+            if not lfutil.inusercache(repo.ui, hash):
+                store = basestore._openstore(repo)
+                success, missing = store.get([(lf, hash)])
+                if len(success) != 1:
+                    raise util.Abort(
+                        _('largefile %s is not in cache and could not be '
+                          'downloaded')  % lf)
+            path = lfutil.usercachepath(repo.ui, hash)
+            fpin = open(path, "rb")
+            for chunk in lfutil.blockstream(fpin):
+                fp.write(chunk)
+            fpin.close()
+        fp.close()
+        err = 0
     return err
 
 def mercurialsinkbefore(orig, sink):
diff --git a/tests/test-largefiles.t b/tests/test-largefiles.t
--- a/tests/test-largefiles.t
+++ b/tests/test-largefiles.t
@@ -1486,7 +1486,10 @@ Cat a largefile
   $ hg cat -r '.^' sub/large4 doesntexist
   large4-modified
   doesntexist: no such file in rev a381d2c8c80e
-  [1]
+  $ hg --cwd sub cat -r '.^' large4
+  large4-modified
+  $ hg --cwd sub cat -r '.^' ../normal3
+  normal3-modified
 
 Test that renaming a largefile results in correct output for status