elem2 = elem2[0]
                         yield (None, elem2, l_no)
                     break
-                index1 = self.unprefixed(elem1['path'])
             if not elem2:
                 try:
                     elem2 = it2.next()
                     for elem1, l_no in it1:
                         yield (elem1, None, l_no)
                     break
-                index2 = self.unprefixed(elem2['path'])
-
-            if index1 < index2:
-                # if the number of dirs in index1 is greater than in index2,
-                # it means that there's a new parent directory in index2, so
-                # it goes first
-                if index1.count('/') > index2.count('/'):
-                    yield (None, elem2, l_no)
-                    elem2 = None
-                else:
-                    yield (elem1, None, l_no)
-                    elem1 = None
-            elif index1 == index2:
-                yield (elem1, elem2, l_no)
-                elem1, elem2 = None, None
-            else:
-                if index2.count('/') > index1.count('/'):
-                    yield (elem1, None, l_no)
-                    elem1 = None
-                else:
-                    yield (None, elem2, l_no)
-                    elem2 = None
+
+            index1 = self.unprefixed(elem1['path'])
+            index2 = self.unprefixed(elem2['path'])
+            i1, i2 = self.compare_indexes(index1, index2)
+
+            yield1 = yield2 = None
+            if i1 is not None:
+                yield1 = elem1
+                elem1 = None
+            if i2 is not None:
+                yield2 = elem2
+                elem2 = None
+            yield (yield1, yield2, l_no)
+
+    def compare_indexes(self, index1, index2):
+        '''
+        Compare iterator indexes and return a tuple in the following form:
+        if index1 < index2, returns (index1, None)
+        if index1 == index2 returns (index1, index2)
+        else: returns (None, index2)
+        '''
+        l1 = index1.split('/')
+        l2 = index2.split('/')
+        length = len(l2) - len(l1)
+
+        if length > 0:
+            return (index1, None)
+        elif length < 0:
+            return (None, index2)
+
+        for i1, i2 in zip(l1, l2):
+            if i1 < i2:
+                return (index1, None)
+            elif i1 > i2:
+                return (None, index2)
+
+        return (index1, index2)
 
     def restore_backup(self, target_path, backup_indexes_paths=[],
                        backup_tar_path=None):
                 tarobj = None,
                 path = index,
                 is_full = is_full,
+                iterator = None,
+                last_itelement = None,
+                last_lno = 0,
                 new_volume_handler = partial(self.new_volume_handler,
                     self._deltatar, self._cwd, is_full, os.path.dirname(index))
             )
             # because the iterator can be walked over completely multiple times,
             # for example if one path if not found in one index and we have to
             # go to the next index.
-            with self._deltatar.iterate_index_path(data["path"]) as it:
-                # find the path in the index
-                d = None
-                l_no = None
-                dpath = None
-                while True:
-                    try:
-                        d, l_no = it.next()
-                    except StopIteration:
-                        break
-
-                    dpath = self._deltatar.unprefixed(d.get('path', ''))
-
-                    if upath == dpath:
-                        break
-
-                if not d:
-                    # file not found, so it's not in the index, so it must be
-                    # removed
-                    if cur_index == 0:
-                        self.delete(path)
-                        return
-                    # this means that the path was found in the first index but
-                    # not in a previous one, so something wrong happened.
-                    else:
-                        self._deltatar.logger.warn('Error restoring file %s from '
-                            'index, not found in index %s' % (path, data['path']))
-                        return
-
-                if d.get('path', '').startswith('delete://'):
-                    self._deltatar.logger.warn(('Strange thing happened, file '
-                        '%s was listed in first index but deleted by another '
-                        'one. Path was ignored and untouched.') % path)
+            d, l_no, dpath = self.find_path_in_index(data, upath)
+            if not d:
+                # file not found, so it's not in the index, so it must be
+                # removed
+                if cur_index == 0:
+                    self.delete(path)
                     return
-                elif d.get('path', '').startswith('snapshot://'):
-                    self.restore_file(d, data, path, l_no, dpath)
+                # this means that the path was found in the first index as listed
+                # not in a previous one, so something wrong happened.
+                else:
+                    self._deltatar.logger.warn('Error restoring file %s from '
+                        'index, not found in index %s' % (path, data['path']))
                     return
-                elif d.get('path', '').startswith('list://'):
-                    continue
+
+            if d.get('path', '').startswith('delete://'):
+                self._deltatar.logger.warn(('Strange thing happened, file '
+                    '%s was listed in first index but deleted by another '
+                    'one. Path was ignored and untouched.') % path)
+                return
+            elif d.get('path', '').startswith('snapshot://'):
+                self.restore_file(d, data, path, l_no, dpath)
+                return
+            elif d.get('path', '').startswith('list://'):
+                continue
 
         self._deltatar.logger.warn(('Error restoring file %s from index, '
                                     'snapshot not found in any index') % path)
 
+    def find_path_in_index(self, data, upath):
+        # NOTE: we restart the iterator sometimes because the iterator can be
+        # walked over completely multiple times, for example if one path if not
+        # found in one index and we have to go to the next index.
+        if data['iterator'] is None:
+            it = data['iterator'] = self._deltatar.iterate_index_path(data["path"])
+            d, l_no = it.next()
+        else:
+            it = data['iterator']
+            d = data['last_itelement']
+            l_no = data['last_lno']
+
+        dpath = self._deltatar.unprefixed(d.get('path', ''))
+
+        while True:
+            if upath == dpath:
+                data['last_itelement'] = d
+                data['last_lno'] = l_no
+                return d, l_no, dpath
+
+            up, dp = self._deltatar.compare_indexes(upath, dpath)
+            # any time upath should have appeared before current dpath, it means
+            # upath is just not in this index and we should stop
+            if dp is None:
+                data['last_itelement'] = d
+                data['last_lno'] = l_no
+                return None, 0, ''
+
+            try:
+                d, l_no = it.next()
+            except StopIteration:
+                data['last_itelement'] = d
+                data['last_lno'] = l_no
+                return None, 0, ''
+            dpath = self._deltatar.unprefixed(d.get('path', ''))
+
     def restore_directories_permissions(self):
         '''
         Restore directory permissions when everything have been restored