diff --git a/fsl/utils/filetree/filetree.py b/fsl/utils/filetree/filetree.py
index 12cfc5a6990ab33f98ea2fd363df3d32ff93541b..344ef150ee3a039d16849b06f66d93c63c83e404 100644
--- a/fsl/utils/filetree/filetree.py
+++ b/fsl/utils/filetree/filetree.py
@@ -1,6 +1,5 @@
 from pathlib import Path, PurePath
 from typing import Tuple, Optional, Dict, Any, Set
-from copy import deepcopy
 from . import parse
 import pickle
 import json
@@ -224,7 +223,7 @@ class FileTree(object):
             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 = self.copy()
         set_tree = new_tree
         while set_parent and set_tree.parent is not None:
             set_tree = set_tree.parent
@@ -308,7 +307,6 @@ class FileTree(object):
             as_dict = json.load(f)
         return from_dict(as_dict)
 
-
     def defines(self, short_names, error=False):
         """
         Checks whether templates are defined for all the `short_names`
@@ -372,7 +370,7 @@ class FileTree(object):
 
         :return: The resulting tree will have empty `variables` dictionaries and updated templates
         """
-        new_tree = deepcopy(self)
+        new_tree = self.copy()
         to_update = new_tree
         while to_update.parent is not None:
             to_update = to_update.parent
@@ -393,6 +391,39 @@ class FileTree(object):
             tree._update_partial_fill()
         self.variables = {}
 
+    def copy(self, ):
+        """
+        Copies the FileTree
+
+        Copies the templates, variables, sub_trees, and parent
+
+        :return: a copy of the FileTree
+        """
+        return self._copy()
+
+    def _copy(self, new_parent=None, new_sub_tree=None):
+        """
+        Helper function for copying a FileTree
+        """
+        if new_sub_tree is None:
+            new_sub_tree = (None, None)
+        new_copy = type(self)(
+            templates=self.templates.copy(),
+            variables=self.variables.copy(),
+            name=self.name,
+            parent=new_parent
+        )
+        new_copy.sub_trees = {name: new_sub_tree[1] if new_sub_tree[0] == name else tree._copy(new_parent=new_copy)
+                              for name, tree in self.sub_trees.items()}
+        if self.parent is not None and new_parent is None:
+            for my_key, ref_tree in self.parent.sub_trees.items():
+                if self is ref_tree:
+                    break
+            else:
+                raise ValueError(f"Sub-tree {self} not found in parent tree")
+            new_copy._parent = self.parent._copy(new_sub_tree=(my_key, new_copy))
+        return new_copy
+
     @classmethod
     def read(cls, tree_name: str, directory='.', partial_fill=False, **variables) -> "FileTree":
         """