diff --git a/fsl/utils/filetree/__init__.py b/fsl/utils/filetree/__init__.py
index 73589296af8b84d6d5677b03dde9058a229b2827..9d31383db6c525d926f9eeb5e558f530700a376c 100644
--- a/fsl/utils/filetree/__init__.py
+++ b/fsl/utils/filetree/__init__.py
@@ -193,9 +193,9 @@ Assuming that the input T1w's already exist, we can then simply run BET for ever
     from fsl.utils.filetree import FileTree
     from fsl.wrappers.bet import bet
     tree = FileTree.read(<tree filename>)
-    variables = tree.get_all_vars('T1w')  # extract the set of variables for all existing T1w files
-    for single_variable_set in variables:
-        T1w_tree = tree.update(**single_variable_set)
+
+    # Iterates over set of variables that correspond to each T1-weighted image file matching the template
+    for T1w_tree in tree.get_all_trees('T1w', glob_vars='all'):
         # get retrieves the filenames based on the current set of variables
         # make_dir=True ensures that the output directory containing the "bet_output" actually exists
         bet(input=T1w_tree.get('T1w'), output=T1w_tree.get('bet_output', make_dir=True), mask=True)
diff --git a/fsl/utils/filetree/filetree.py b/fsl/utils/filetree/filetree.py
index 93bf98070bfffd4054af95a62105e7e3cb9deb58..fb7aa082f47f432666feed07b00474c3c5c23d70 100644
--- a/fsl/utils/filetree/filetree.py
+++ b/fsl/utils/filetree/filetree.py
@@ -171,7 +171,7 @@ class FileTree(object):
         :return: sorted sequence of paths
         """
         text, variables = self.get_template(short_name)
-        return tuple(utils.get_all(text, variables, glob_vars=glob_vars))
+        return tuple(str(Path(fn)) for fn in utils.get_all(text, variables, glob_vars=glob_vars))
 
     def get_all_vars(self, short_name: str, glob_vars=()) -> Tuple[Dict[str, str]]:
         """
@@ -185,16 +185,33 @@ class FileTree(object):
         """
         return tuple(self.extract_variables(short_name, fn) for fn in self.get_all(short_name, glob_vars=glob_vars))
 
+    def get_all_trees(self, short_name: str, global_vars=()) -> Tuple["FileTree"]:
+        """
+        Gets all the trees that generate the existing files matching the pattern
+
+        tree.get_all(short_name) == tuple(tree.get(short_name) for tree in tree.get_all_trees(short_name))
+
+        :param short_name: short name of the path template
+        :param glob_vars: sequence of undefined variables that can take any possible values when looking for matches on the disk.
+            Any defined variables in `glob_vars` will be ignored.
+            If glob_vars is set to 'all', all undefined variables will be used to look up matches.
+        :return: sequence of FileTrees used to generate each file on disk matching the pattern of `short_name`
+        """
+        return tuple(self.update(**vars) for vars in self.get_all_vars(short_name, glob_vars=global_vars))
+
     def update(self, **variables) -> "FileTree":
         """
-        Creates a new filetree with updated variables
+        Creates a new FileTree with updated variables
 
         :param variables: new values for the variables
-            Setting variables to None will explicitly unset them
+            Setting a variable to None will cause the variable to be unset
         :return: New FileTree with same templates for directory names and filenames, but updated variables
         """
         new_tree = deepcopy(self)
         new_tree.variables.update(variables)
+        for key, value in variables.items():
+            if value is None:
+                del new_tree.variables[key]
         return new_tree
 
     def extract_variables(self, short_name: str, filename: str) -> Dict[str, str]:
diff --git a/fsl/utils/filetree/utils.py b/fsl/utils/filetree/utils.py
index 4ad5f63aff9164531b1a491056f9f9574f963b70..e7dd4aad3347c678e32217e09eecf33d2ecdee35 100644
--- a/fsl/utils/filetree/utils.py
+++ b/fsl/utils/filetree/utils.py
@@ -170,6 +170,8 @@ def extract_variables(template, filename, known_vars=None):
                     raise ValueError('Multiple values found for {}'.format(var))
             else:
                 extracted_value[var] = value
+        if any('/' in value for value in extracted_value.values()):
+            continue
         for name in find_variables(template):
             if name not in extracted_value:
                 extracted_value[name] = None
diff --git a/tests/test_filetree/test_read.py b/tests/test_filetree/test_read.py
index b27984477218cd69f757199948865c2a06e6f8d1..954f671e791ca8edf3d3ef0a8932488e3669f7ab 100644
--- a/tests/test_filetree/test_read.py
+++ b/tests/test_filetree/test_read.py
@@ -77,8 +77,8 @@ def test_custom_tree():
     assert len(tree.get_all('sub_file', glob_vars='all')) == 2
     assert len(tree.get_all('sub_file')) == 1
     assert len(tree.update(opt=None).get_all('sub_file')) == 1
-    assert len(tree.update(opt=None).get_all('sub_file', glob_vars=['opt'])) == 1
-    assert len(tree.update(opt=None).get_all('sub_file', glob_vars='all')) == 1
+    assert len(tree.update(opt=None).get_all('sub_file', glob_vars=['opt'])) == 2
+    assert len(tree.update(opt=None).get_all('sub_file', glob_vars='all')) == 2
 
     for fn, settings in zip(tree.get_all('sub_file', glob_vars='all'),
                             tree.get_all_vars('sub_file', glob_vars='all')):
@@ -90,6 +90,10 @@ def test_custom_tree():
         tree.get_all('opt_file')
     assert len(tree.get_all('opt_file', glob_vars=['opt'])) == 1
 
+    for short_name in ('sub_file', 'opt_file'):
+        for glob_vars in (['opt'], 'all'):
+            assert tree.get_all(short_name, glob_vars) == tuple(stree.get(short_name) for stree in tree.get_all_trees(short_name, glob_vars))
+
     for vars in ({'opt': None}, {'opt': 'test'}):
         filename = tree.update(**vars).get('sub_file')
         assert vars == tree.extract_variables('sub_file', filename)
diff --git a/tests/test_filetree/test_template.py b/tests/test_filetree/test_template.py
index 96ecc18f00adb1add2b191c8d3744460f1c02bc6..c4042078df8a762c3affb5b2d98e1c63cb9a4b81 100644
--- a/tests/test_filetree/test_template.py
+++ b/tests/test_filetree/test_template.py
@@ -21,3 +21,7 @@ def test_get_variables():
         utils.extract_variables('{var}[_{other_var}]_{var}', 'test_foo_bar')
     with pytest.raises(ValueError):
         utils.extract_variables('bar{var}[_{other_var}]_{var}', 'test')
+
+    assert {'subject': '01', 'session': 'A'} == utils.extract_variables('sub-{subject}/[ses-{session}]/T1w.nii.gz', 'sub-01/ses-A/T1w.nii.gz')
+    with pytest.raises(ValueError):
+        utils.extract_variables('sub-{subject}/[ses-{session}]/T1w.nii.gz', 'sub-01/other/T1w.nii.gz')