diff --git a/fsl/utils/filetree/filetree.py b/fsl/utils/filetree/filetree.py
index 0b97268f2dd82580550e1c1d8ce3fda5498b6cfd..a58744668d07767d477b4021e33fab50c10368e7 100644
--- a/fsl/utils/filetree/filetree.py
+++ b/fsl/utils/filetree/filetree.py
@@ -1,10 +1,11 @@
 from pathlib import Path, PurePath
-from typing import Tuple, Optional, List, Dict, Any, Set
+from typing import Tuple, Optional, Dict, Any, Set
 from copy import deepcopy
 from . import parse
 import pickle
 import os.path as op
 from . import utils
+from fsl.utils.deprecated import deprecated
 
 
 class MissingVariable(KeyError):
@@ -257,12 +258,38 @@ class FileTree(object):
             raise IOError("Pickle file did not contain %s object" % cls)
         return res
 
-    def exists(self, short_names, on_disk=False, error=False, glob_vars=()):
+    def defines(self, short_names, error=False):
+        """
+        Checks whether templates are defined for all the `short_names`
+
+        :param short_names: sequence of expected short names to exist in the tree
+        :param error: if True raises ValueError if any `short_names` are undefined
+        :return: True if all are defined, False otherwise
+        :raise: ValueError if `error` is set to True and any template is missing
+        """
+        if isinstance(short_names, str):
+            short_names = (short_names, )
+
+        def single_test(short_name):
+            try:
+                self._get_template_tree(short_name)
+            except KeyError:
+                return True
+            return False
+
+        missing = tuple(name for name in short_names if single_test(name))
+
+        if len(missing) > 0:
+            if error:
+                raise ValueError("Provided Filetree is missing template definitions for {}".format(missing))
+            return False
+        return True
+
+    def on_disk(self, short_names, error=False, glob_vars=()):
         """
-        Checks whether the short_names are defined in the tree (and optional exist on the disk)
+        Checks whether at least one file exists for every file in `short_names`
 
         :param short_names: list of expected short names to exist in the tree
-        :param on_disk: if True checks whether the files exist on disk
         :param error: if True raises a helpful error when the check fails
         :param glob_vars: sequence of undefined variables that can take any possible values when looking for matches on the disk
             If `glob_vars` contains any defined variables, it will be ignored.
@@ -271,34 +298,34 @@ class FileTree(object):
             - ValueError if error is set and the tree is incomplete
             - IOError if error is set and any files are missing from the disk
         """
+        self.defines(short_names, error=error)
+
         if isinstance(short_names, str):
             short_names = (short_names, )
 
-        def single_test(short_name):
-            try:
-                self._get_template_tree(short_name)
-            except KeyError:
-                return True
+        try:
+            missing = tuple(name for name in short_names if len(self.get_all(name, glob_vars=glob_vars)) == 0)
+        except KeyError:
+            if error:
+                raise
             return False
-
-        missing = tuple(name for name in short_names if single_test(name))
         if len(missing) > 0:
             if error:
-                raise ValueError("Provided Filetree is missing file definitions for {}".format(missing))
+                raise IOError("Failed to find any files on disk for {}".format(missing))
             return False
-        if on_disk:
-            try:
-                missing = tuple(name for name in short_names if len(self.get_all(name, glob_vars=glob_vars)) == 0)
-            except KeyError:
-                if error:
-                    raise
-                return False
-            if len(missing) > 0:
-                if error:
-                    raise IOError("Failed to find any files existing for {}".format(missing))
-                return False
         return True
 
+    @deprecated(rin='2.4', msg='Use FileTree.defines or FileTree.on_disk instead')
+    def exists(self, short_names, on_disk=False, error=False, glob_vars=()):
+        """
+        Deprecated in favor of :meth:`on_disk` and :meth:`defines`.
+        """
+        if on_disk:
+            return self.on_disk(short_names, error=error, glob_vars=glob_vars)
+        else:
+            return self.defines(short_names, error=error, glob_vars=glob_vars)
+
+
     @classmethod
     def read(cls, tree_name: str, directory='.', **variables) -> "FileTree":
         """
diff --git a/tests/test_filetree/test_read.py b/tests/test_filetree/test_read.py
index cba2625e19601722301e5b3b68f26fa472152637..00bd310106b422fecff8029045c38c44ed943ae9 100644
--- a/tests/test_filetree/test_read.py
+++ b/tests/test_filetree/test_read.py
@@ -34,17 +34,17 @@ def test_complicated_tree():
     same_path(tree.update(hemi='L').get('T1w_32k/white'), L_white)
     same_path(tree.sub_trees['T1w_32k'].update(hemi='L').get('white'), L_white)
 
-    assert tree.exists(('T1w_32k/white', ))
-    assert tree.exists('T1w_32k/white')
-    assert not tree.exists(('T1w_32k/white_misspelled', ))
-    assert not tree.exists(('T1w_32k/white', 'T1w_32k/white_misspelled', ))
-    assert not tree.exists(('T1w_32k_err/white', ))
-    assert not tree.exists(('../test'))
+    assert tree.defines(('T1w_32k/white', ))
+    assert tree.defines('T1w_32k/white')
+    assert not tree.defines(('T1w_32k/white_misspelled', ))
+    assert not tree.defines(('T1w_32k/white', 'T1w_32k/white_misspelled', ))
+    assert not tree.defines(('T1w_32k_err/white', ))
+    assert not tree.defines(('../test'))
     with pytest.raises(ValueError):
-        assert not tree.exists(('../test'), error=True)
+        assert not tree.defines(('../test'), error=True)
     with pytest.raises(ValueError):
-        tree.exists(('T1w_32k_err/white', ), error=True)
-    assert tree.exists(('T1w_32k/white', ), error=True)
+        tree.defines(('T1w_32k_err/white', ), error=True)
+    assert tree.defines(('T1w_32k/white', ), error=True)
 
 
 def test_parent_tree():
@@ -110,14 +110,14 @@ def test_custom_tree():
         assert vars == tree.extract_variables('sub_file', filename)
     assert {'opt': None} == tree.extract_variables('sub_file', tree.get('sub_file'))
 
-    assert tree.exists(('sub_file', 'opt_file'), error=True, on_disk=True, glob_vars=['opt'])
-    assert tree.exists(('sub_file', 'opt_file'), on_disk=True, glob_vars=['opt'])
-    assert not tree.exists(('sub_file', 'opt_file'), error=False, on_disk=True)
+    assert tree.on_disk(('sub_file', 'opt_file'), error=True, glob_vars=['opt'])
+    assert tree.on_disk(('sub_file', 'opt_file'), glob_vars=['opt'])
+    assert not tree.on_disk(('sub_file', 'opt_file'), error=False)
     with pytest.raises(KeyError):
-        assert tree.exists(('sub_file', 'opt_file'), error=True, on_disk=True)
-    assert not tree.update(opt='test2').exists(('sub_file', 'opt_file'), on_disk=True)
+        assert tree.on_disk(('sub_file', 'opt_file'), error=True)
+    assert not tree.update(opt='test2').on_disk(('sub_file', 'opt_file'))
     with pytest.raises(IOError):
-        tree.update(opt='test2').exists(('sub_file', 'opt_file'), on_disk=True, error=True)
+        tree.update(opt='test2').on_disk(('sub_file', 'opt_file'), error=True)
 
     assert tree.template_variables() == {'opt'}
     assert tree.template_variables(optional=False) == {'opt'}