diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb8662e15e3b962fc8ac8f974302205809aa4b19..7c458aed9609b71662800d4d69b73755ed263718 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
   output
 - New class for collecting information for exporting tables, e.g., to
   metadata repositories
+- new name parsing
+- new test for software folder structure
+- new assure_name_is function
 
 ### Changed ###
 
diff --git a/integrationtests/crawl.py b/integrationtests/crawl.py
index e439510fd7308888e9071476905f486c82769dc5..2bec8b0acc98fdc7dd54c10cb360aac209e30978 100755
--- a/integrationtests/crawl.py
+++ b/integrationtests/crawl.py
@@ -33,7 +33,7 @@ from caosadvancedtools.cfood import fileguide
 from caosadvancedtools.crawler import FileCrawler
 from caosadvancedtools.guard import INSERT, UPDATE
 from scifolder import (AnalysisCFood, ExperimentCFood, ProjectCFood,
-                       PublicationCFood, SimulationCFood)
+                       PublicationCFood, SimulationCFood, SoftwareCFood)
 
 try:
     from sss_helper import get_argument_parser, print_success
@@ -87,7 +87,7 @@ if __name__ == "__main__":
     c = FileCrawler(files=files, use_cache=True,
                     interactive=False, hideKnown=False,
                     cfood_types=[ProjectCFood,
-                                 ExperimentCFood, AnalysisCFood,
+                                 ExperimentCFood, AnalysisCFood, SoftwareCFood,
                                  PublicationCFood, SimulationCFood,
                                  ])
 
diff --git a/integrationtests/extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.md b/integrationtests/extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.md
deleted file mode 100644
index 4470e62b71fe60e0c5dddd3c0a9a88790396b16e..0000000000000000000000000000000000000000
--- a/integrationtests/extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
----
-responsible:	
-- First Person
-description: 	A description of an example analysis.
-
-results:
-- file:	"images/*.png"
-  description:  an example reference to a results file
-
-sources:
-- file: /ExperimentalData/2010_TestProject/2019-02-03_something/
-  description:  an example reference to an experiment
-
-revisionOf:
-- ../2019-02-03
-
-scripts:
-- analyse.py
-
-tags:
-- collagen
-- time sweep
-- frequency sweep
-...
diff --git a/integrationtests/extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx b/integrationtests/extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..94afaa4f0af396997ec5582bc377245524817e00
Binary files /dev/null and b/integrationtests/extroot/DataAnalysis/2010_TestProject/2019-02-03_something/README.xlsx differ
diff --git a/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_V1.0-rc1/README.xlsx b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_V1.0-rc1/README.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..37024543a36f17e717d472a63576c017a138a1de
Binary files /dev/null and b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_V1.0-rc1/README.xlsx differ
diff --git a/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_V1.0-rc1/analyse.py b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_V1.0-rc1/analyse.py
new file mode 100644
index 0000000000000000000000000000000000000000..02e78c5b0b1ee1896eb16b2fcbd2e9178d091212
--- /dev/null
+++ b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_V1.0-rc1/analyse.py
@@ -0,0 +1 @@
+sdkflj2435j4'4rg
diff --git a/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_V1.0-rc1/calc.py b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_V1.0-rc1/calc.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec7f06eb8eb435d3ce821792411e781390ae5b82
--- /dev/null
+++ b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_V1.0-rc1/calc.py
@@ -0,0 +1 @@
+sldfkjsldfjk
diff --git a/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/README.md b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d844a2ddf0d87d303c69b9107a366f2e34b6d03c
--- /dev/null
+++ b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/README.md
@@ -0,0 +1,15 @@
+---
+responsible: Responsible, Only
+description: 	A description of this example analysis.
+
+sources:
+- file:	"/ExperimentalData/2010_TestProject/2019-02-03/*.dat"
+  description:  an example reference to a results file
+
+sourceCode:
+- file: plot.py
+  description: a plotting script
+binaries:
+- file: example.deb
+  description: the binary file
+...
diff --git a/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/example.deb b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/example.deb
new file mode 100644
index 0000000000000000000000000000000000000000..685dc927597934520f3189024f4e85e46301d2a3
--- /dev/null
+++ b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/example.deb
@@ -0,0 +1 @@
+binary file
diff --git a/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/plot.py b/integrationtests/extroot/Software/2010_TestSoftware/2019-02-03_v0.1/plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/README.md b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a47ea6e105c20d050ddf2fdc8cd29d4685ba30bf
--- /dev/null
+++ b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/README.md
@@ -0,0 +1,15 @@
+---
+responsible:	
+- Only Responsible MPI DS
+description: 	A description of this example analysis.
+
+sources:
+- file:	"/ExperimentalData/2010_TestProject/2019-02-03/*.dat"
+  description:  an example reference to a results file
+
+sourceCode:
+- file: plot.py
+  description: a plotting script
+- file: calc.py
+  description: a calc script
+...
diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/calc.py b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/calc.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/plot.py b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03/plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-03_second/README.xlsx b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03_second/README.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..1a2262719f155893c8d88580ed0556f684a4c1b7
Binary files /dev/null and b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03_second/README.xlsx differ
diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-03_second/analyse.py b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03_second/analyse.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-03_second/release.deb b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03_second/release.deb
new file mode 100644
index 0000000000000000000000000000000000000000..92861e91dfa1bd37957fc9916ab1afd8ff76b40b
--- /dev/null
+++ b/integrationtests/extroot/Software/2020NewProject0X/2020-02-03_second/release.deb
@@ -0,0 +1 @@
+kdjf
diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/README.md b/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..97b7137af372c127ee01458c9844b5ff10fd464b
--- /dev/null
+++ b/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/README.md
@@ -0,0 +1,15 @@
+---
+responsible:	
+- Some Responsible
+- Responsible, No, MPI DS
+description: 	A description of this example analysis.
+
+sources:
+- file:	"/ExperimentalData/2010_TestProject/2019-02-03/*.dat"
+  description:  an example reference to a results file
+
+sourceCode: plot.py
+binaries:
+- file: example.deb
+  description: the binary file
+...
diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/example.deb b/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/example.deb
new file mode 100644
index 0000000000000000000000000000000000000000..685dc927597934520f3189024f4e85e46301d2a3
--- /dev/null
+++ b/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/example.deb
@@ -0,0 +1 @@
+binary file
diff --git a/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/plot.py b/integrationtests/extroot/Software/2020NewProject0X/2020-02-04/plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/integrationtests/filldb.sh b/integrationtests/filldb.sh
index da1abc7076b8f65dfc41277fd2b41dd9a5f65996..98d22347bd2d40e8384a2a217452fd3ba5bc445f 100755
--- a/integrationtests/filldb.sh
+++ b/integrationtests/filldb.sh
@@ -5,5 +5,6 @@ python3 -m caosadvancedtools.loadFiles /opt/caosdb/mnt/extroot/ExperimentalData
 python3 -m caosadvancedtools.loadFiles /opt/caosdb/mnt/extroot/DataAnalysis
 python3 -m caosadvancedtools.loadFiles /opt/caosdb/mnt/extroot/SimulationData
 python3 -m caosadvancedtools.loadFiles /opt/caosdb/mnt/extroot/Publications
+python3 -m caosadvancedtools.loadFiles /opt/caosdb/mnt/extroot/Software
 python3 insert_model.py 
 python3 crawl.py /
diff --git a/integrationtests/insert_model.py b/integrationtests/insert_model.py
index 1dcf5bdb888988089e554dc41bb20fbbe5e60e23..2289f72e83545db0e7eacedfa52868507b6c4760 100755
--- a/integrationtests/insert_model.py
+++ b/integrationtests/insert_model.py
@@ -1,5 +1,11 @@
 #!/usr/bin/env python3
+import caosdb as db
 from caosmodels.parser import parse_model_from_yaml
 
 model = parse_model_from_yaml("model.yml")
 model.sync_data_model(noquestion=True)
+
+if len(db.execute_query("FIND Property alias")) == 0:
+    al = db.Property(name="alias")
+    al.add_parent(name="name")
+    al.insert()
diff --git a/integrationtests/model.yml b/integrationtests/model.yml
index 35f5ef244a85248c45eb79c359dbc5827ea3bc05..39659c008a1c9297a4470f0e5598074616af5aad 100644
--- a/integrationtests/model.yml
+++ b/integrationtests/model.yml
@@ -10,6 +10,14 @@ Experiment:
   #recommended_properties:
     responsible:
 Project:
+SoftwareVersion:
+  recommended_properties:
+    version:
+      datatype: TEXT 
+      description: 'First name of a Person.'
+    binaries:
+    sourceCode:
+    Software:
 Person:
   obligatory_properties:
     firstName:
diff --git a/integrationtests/test_cache.py b/integrationtests/test_cache.py
index cb9c174e5618cff77b0664bd7d7d43b28aefcca3..4b0a6cedc390b1268e8d2d89393e19a27a83b3be 100644
--- a/integrationtests/test_cache.py
+++ b/integrationtests/test_cache.py
@@ -22,45 +22,54 @@
 #
 # ** end header
 
+import os
+import unittest
+from tempfile import NamedTemporaryFile
+
 import caosdb as db
 from caosadvancedtools.cache import UpdateCache
 
 
-def setup():
-    try:
-        db.execute_query("FIND Test*").delete()
-    except Exception:
-        pass
-
+class CacheTest(unittest.TestCase):
+    def empty_db(self):
+        try:
+            db.execute_query("FIND Test*").delete()
+        except Exception:
+            pass
 
-def teardown():
-    setup()
+    def setUp(self):
+        self.cache = NamedTemporaryFile(delete=False).name
+        os.remove(self.cache)
+        self.empty_db()
 
+    def tearDown(self):
+        self.empty_db()
+        os.remove(self.cache)
 
-def test_same_old_different_new():
-    """Formerly, inserting two containers with different changes to the
-    same entity into the update cache would result in an
-    IntegrityException.
+    def test_same_old_different_new(self):
+        """Formerly, inserting two containers with different changes to the
+        same entity into the update cache would result in an
+        IntegrityException.
 
-    """
-    rt = db.RecordType(name="TestType").insert()
-    db.Property(name="TestProp1", datatype=db.TEXT).insert()
-    db.Property(name="TestProp2", datatype=db.TEXT).insert()
-    rec = db.Record(name="TestRecord").add_parent(rt).insert()
+        """
+        rt = db.RecordType(name="TestType").insert()
+        db.Property(name="TestProp1", datatype=db.TEXT).insert()
+        db.Property(name="TestProp2", datatype=db.TEXT).insert()
+        rec = db.Record(name="TestRecord").add_parent(rt).insert()
 
-    # add TestProp1 to TestRecord
-    rec.add_property(name="TestProp1", value="blub")
-    cont = db.Container().append(rec)
+        # add TestProp1 to TestRecord
+        rec.add_property(name="TestProp1", value="blub")
+        cont = db.Container().append(rec)
 
-    update = UpdateCache()
-    run_id = "a"
-    update.insert(cont, run_id)
-    assert len(update.get_updates(run_id)) == 1
+        update = UpdateCache(db_file=self.cache)
+        run_id = "a"
+        update.insert(cont, run_id)
+        assert len(update.get_updates(run_id)) == 1
 
-    # duplicate and add TestProp2 to TestRecord
-    rec = db.execute_query("FIND Record TestRecord", unique=True)
-    rec.add_property(name="TestProp2", value="bla")
-    cont = db.Container().append(rec)
-    # same old digest, different new digest
-    update.insert(cont, run_id)
-    assert len(update.get_updates(run_id)) == 2
+        # duplicate and add TestProp2 to TestRecord
+        rec = db.execute_query("FIND Record TestRecord", unique=True)
+        rec.add_property(name="TestProp2", value="bla")
+        cont = db.Container().append(rec)
+        # same old digest, different new digest
+        update.insert(cont, run_id)
+        assert len(update.get_updates(run_id)) == 2
diff --git a/integrationtests/test_crawler_with_cfoods.py b/integrationtests/test_crawler_with_cfoods.py
index cc6f06771c48b41cdbba928051e0620e60586587..c39c3fc67d7ca30e3d013ac205ef398de216ad9c 100755
--- a/integrationtests/test_crawler_with_cfoods.py
+++ b/integrationtests/test_crawler_with_cfoods.py
@@ -266,3 +266,215 @@ class CrawlerTest(unittest.TestCase):
 
         # Test type
         self.assertEqual(pub.parents[0].name, "Thesis")
+
+    def test_software(self):
+        ########################
+        # # overall software # #
+        ########################
+
+        sw = db.execute_query("FIND Record Software")
+        assert len(sw) == 5
+
+        ps = db.execute_query("FIND RecordType Software with name!='Software'")
+        assert len(ps) == 2
+
+        ##############################
+        # # first software version # #
+        ##############################
+        ana = db.execute_query(
+            "FIND Software with version='V1.0-rc1'", unique=True)
+
+        sw = db.execute_query(
+            "FIND Software with name='2010_TestSoftware'", unique=True)
+        assert sw.get_property("alias").value == "TestSoftware"
+
+        # The software record should inherit from the correct software
+        assert sw.id == ana.get_parents()[0].id
+        assert ana.name == "TestSoftware_V1.0-rc1"
+
+        # There should not be a file as binary
+        self.assertIsNone(ana.get_property("binaries"))
+
+        # There should be a file as script attached with path plot.py
+        datfile = get_entity_with_id(ana.get_property("sourceCode").value[0])
+        datfile2 = get_entity_with_id(ana.get_property("sourceCode").value[1])
+
+        for d in [datfile, datfile2]:
+            if datfile.path.endswith("analyse.py"):
+                assert datfile.description == "a simple script"
+            elif datfile.path.endswith("calc.py"):
+                assert datfile.description == "some calculation"
+            else:
+                raise Exception("unkown file")
+
+        # Should have two responsible person
+        self.assertIsNotNone(ana.get_property("responsible"))
+        person = db.Record(id=ana.get_property("responsible").value[0])
+        person.retrieve()
+        person2 = db.Record(id=ana.get_property("responsible").value[1])
+        person2.retrieve()
+
+        for fn in ["Second", "First"]:
+            found = False
+
+            for p in [person, person2]:
+                if p.get_property("firstname").value == fn:
+                    found = True
+
+            if not found:
+                raise Exception("Did not find person")
+
+        # Should have a description
+        self.assertIsNotNone(ana.description)
+
+        #######################
+        # # second software version # #
+        #######################
+        ana = db.execute_query(
+            "FIND Software with version='v0.1'", unique=True)
+
+        sw = db.execute_query(
+            "FIND Software with name='2010_TestSoftware'", unique=True)
+
+        # The software record should inherit from the correct software
+        assert sw.id == ana.get_parents()[0].id
+        # The software should have the date
+        assert "2019-02-03" == ana.get_property("date").value
+
+        # There should be a file as binary attached with path release.deb
+        datfile_id = ana.get_property("binaries").value[0]
+        datfile = get_entity_with_id(datfile_id)
+        assert os.path.basename(datfile.path) == "example.deb"
+
+        # There should be a file as script attached with path plot.py
+        datfile_id = ana.get_property("sourceCode").value[0]
+        datfile = get_entity_with_id(datfile_id)
+        assert os.path.basename(datfile.path) == "plot.py"
+
+        # Should have a responsible person
+        self.assertIsNotNone(ana.get_property("responsible"))
+        person = db.Record(id=ana.get_property("responsible").value[0])
+        person.retrieve()
+        self.assertEqual("Only", person.get_property("firstname").value)
+
+        # Should have a description
+        assert "example" in ana.description
+
+        #######################
+        # # third software version # #
+        #######################
+        ana = db.execute_query(
+            "FIND Software with date='2020-02-04' and not version",
+            unique=True)
+
+        sw = db.execute_query(
+            "FIND Software with name='2020NewProject0X'", unique=True)
+
+        # The software record should inherit from the correct software
+        assert sw.id == ana.get_parents()[0].id
+        # The software should have the date
+        assert "2020-02-04" == ana.get_property("date").value
+
+        # There should be a file as binary attached with path release.deb
+        datfile_id = ana.get_property("binaries").value[0]
+        datfile = get_entity_with_id(datfile_id)
+        assert os.path.basename(datfile.path) == "example.deb"
+
+        # There should be a file as script attached with path plot.py
+        datfile_id = ana.get_property("sourceCode").value[0]
+        datfile = get_entity_with_id(datfile_id)
+        assert os.path.basename(datfile.path) == "plot.py"
+
+        # Should have two responsible person
+        self.assertIsNotNone(ana.get_property("responsible"))
+        person = db.Record(id=ana.get_property("responsible").value[0])
+        person.retrieve()
+        person2 = db.Record(id=ana.get_property("responsible").value[1])
+        person2.retrieve()
+
+        for fn in ["Some", "No"]:
+            found = False
+
+            for p in [person, person2]:
+                if p.get_property("firstname").value == fn:
+                    found = True
+
+            if not found:
+                raise Exception("Did not find person")
+
+        # Should have a description
+        assert "example" in ana.description
+
+        #######################
+        # # fourth software version # #
+        #######################
+        ana = db.execute_query(
+            "FIND Software with date='2020-02-03' and not version",
+            unique=True)
+
+        sw = db.execute_query(
+            "FIND Software with name='2020NewProject0X'", unique=True)
+        assert sw.get_property("alias").value == "NewProject0X"
+
+        # The software record should inherit from the correct software
+        assert sw.id == ana.get_parents()[0].id
+        # The software should have the date
+        assert "2020-02-03" == ana.get_property("date").value
+
+        # There should not be a file as binary
+        self.assertIsNone(ana.get_property("binaries"))
+
+        # There should be a file as script attached with path plot.py
+        datfile = get_entity_with_id(ana.get_property("sourceCode").value[0])
+        datfile2 = get_entity_with_id(ana.get_property("sourceCode").value[1])
+
+        for d in [datfile, datfile2]:
+            if datfile.path.endswith("plot.py"):
+                assert datfile.description == "a plotting script"
+            elif datfile.path.endswith("calc.py"):
+                assert datfile.description == "a calc script"
+            else:
+                raise Exception("unkown file")
+
+        # Should have a responsible person
+        self.assertIsNotNone(ana.get_property("responsible"))
+        person = db.Record(id=ana.get_property("responsible").value[0])
+        person.retrieve()
+        self.assertEqual("Only", person.get_property("firstname").value)
+        self.assertEqual("Responsible", person.get_property("lastname").value)
+
+        # Should have a description
+        assert "example" in ana.description
+
+        ##############################
+        # # fifth software version # #
+        ##############################
+        ana = db.execute_query(
+            "FIND Software with version='second'", unique=True)
+
+        sw = db.execute_query(
+            "FIND Software with name='2020NewProject0X'", unique=True)
+        assert sw.get_property("alias").value == "NewProject0X"
+
+        # The software record should inherit from the correct software
+        assert sw.id == ana.get_parents()[0].id
+        assert ana.name == "NewProject0X_second"
+
+        # There should be a file as binary attached with path release.deb
+        datfile_id = ana.get_property("binaries").value[0]
+        datfile = get_entity_with_id(datfile_id)
+        assert os.path.basename(datfile.path) == "release.deb"
+
+        # There should be a file as script attached with path plot.py
+        datfile_id = ana.get_property("sourceCode").value[0]
+        datfile = get_entity_with_id(datfile_id)
+        assert os.path.basename(datfile.path) == "analyse.py"
+
+        # Should have a responsible person
+        self.assertIsNotNone(ana.get_property("responsible"))
+        person = db.Record(id=ana.get_property("responsible").value[0])
+        person.retrieve()
+        self.assertEqual("First", person.get_property("firstname").value)
+
+        # Should have a description
+        self.assertIsNotNone(ana.description)
diff --git a/src/caosadvancedtools/cfood.py b/src/caosadvancedtools/cfood.py
index 341594cf2efea5dd9ebdf0789fa292062053e4d6..54a6b8093748a2e9ee5986bf5efe2e9f0dbdb078 100644
--- a/src/caosadvancedtools/cfood.py
+++ b/src/caosadvancedtools/cfood.py
@@ -412,24 +412,24 @@ def assure_object_is_in_list(obj, containing_object, property_name,
         to_be_updated.append(containing_object)
 
 
-# TOOD rename to is
-# switch arugments and check for old sequence
-def assure_has_description(entity, description, to_be_updated=None,
-                           force=False):
+def assure_special_is(entity, value, kind, to_be_updated=None, force=False):
     """
-    Checks whether `entity` has the description that is passed.
+    Checks whether `entity` has the name or description that is passed.
 
     If this is the case this function ends. Otherwise the entity is assigned
-    a new description. The list to_be_updated is supplied, the entity is added to
+    a new name. The list to_be_updated is supplied, the entity is added to
     the list in order to indicate, that the entity `entity` should be updated.
     Otherwise it is directly updated
     """
 
-    if entity.description == description:
+    if kind not in ["name", "description"]:
+        raise RuntimeError("Function cannot be used to set {}".format(kind))
+
+    if entity.__getattribute__(kind) == value:
         return
 
-    logger.debug("UPDATE: set description of entity {}".format(entity.id))
-    entity.description = description
+    logger.debug("UPDATE: set {} of entity {}".format(kind, entity.id))
+    entity.__setattr__(kind,  value)
 
     if to_be_updated is None:
         if force:
@@ -440,6 +440,37 @@ def assure_has_description(entity, description, to_be_updated=None,
         to_be_updated.append(entity)
 
 
+def assure_name_is(entity, name, to_be_updated=None, force=False):
+    """
+    Checks whether `entity` has the name that is passed.
+
+    If this is the case this function ends. Otherwise the entity is assigned
+    a new name. The list to_be_updated is supplied, the entity is added to
+    the list in order to indicate, that the entity `entity` should be updated.
+    Otherwise it is directly updated
+    """
+
+    assure_special_is(entity, name, "name", to_be_updated=to_be_updated,
+                      force=force)
+
+
+# TOOD rename to is
+# switch arugments and check for old sequence
+def assure_has_description(entity, description, to_be_updated=None,
+                           force=False):
+    """
+    Checks whether `entity` has the description that is passed.
+
+    If this is the case this function ends. Otherwise the entity is assigned
+    a new description. The list to_be_updated is supplied, the entity is added to
+    the list in order to indicate, that the entity `entity` should be updated.
+    Otherwise it is directly updated
+    """
+
+    assure_special_is(entity, description, "description",
+                      to_be_updated=to_be_updated, force=force)
+
+
 def assure_has_parent(entity, parent, to_be_updated=None,
                       force=False, unique=True):
     """
diff --git a/src/caosadvancedtools/crawler.py b/src/caosadvancedtools/crawler.py
index e5bb738c5dc542bbf127a5163d91b2e748959915..6d706bb37a05549989ade5e77325bf513fc07a34 100644
--- a/src/caosadvancedtools/crawler.py
+++ b/src/caosadvancedtools/crawler.py
@@ -45,10 +45,10 @@ import subprocess
 import traceback
 import uuid
 from datetime import datetime
+from sqlite3 import IntegrityError
 
 import caosdb as db
 from caosdb.exceptions import TransactionError
-from sqlite3 import IntegrityError
 
 from .cache import Cache, UpdateCache, get_pretty_xml
 from .cfood import RowCFood, add_files, get_ids_for_entities_with_names
@@ -293,7 +293,7 @@ class Crawler(object):
             except Exception as e:
                 try:
                     DataModelProblems.evaluate_exception(e)
-                except BaseException:
+                except Exception:
                     pass
                 logger.info("Failed during execution of {}!".format(
                     cfood.__class__.__name__))
@@ -365,6 +365,7 @@ ____________________\n""".format(i+1, len(pending_changes)) + str(el[3]))
 
         """
         from xml.sax.saxutils import escape
+
         # TODO move path related stuff to sss_helper
         form = """
 <html>
diff --git a/src/caosadvancedtools/utils.py b/src/caosadvancedtools/utils.py
index cb790a513dd3c15e9e19d9c9e377b95e02d452c7..2504f56976e2f6122f3e3468db1c7ae807bbb8cd 100644
--- a/src/caosadvancedtools/utils.py
+++ b/src/caosadvancedtools/utils.py
@@ -4,7 +4,8 @@
 # ** header v3.0
 # This file is a part of the CaosDB Project.
 #
-# Copyright (C) 2019 Henrik tom Wörden
+# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
+# Copyright (C) 2020 Henrik tom Wörden <h.tomwoerden@indiscale.com>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -58,10 +59,20 @@ def string_to_person(person):
     """
     Creates a Person Record from a string.
 
-    Currently only the format <Firstname> <Lastname> <*> is supported.
+    The following formats are supported:
+    - `<Firstname> <Lastname> <*>`
+    - `<Lastname(s)>,<Firstname(s)>,<*>`
+
+    The part after the name can be used for an affiliation for example.
     """
-    firstname = person.split(" ")[0]
-    lastname = person.split(" ")[1]
+
+    if "," in person:
+        firstname = person.split(",")[1].strip()
+        lastname = person.split(",")[0].strip()
+    else:
+        firstname = person.split(" ")[0].strip()
+        lastname = person.split(" ")[1].strip()
+
     pr = db.Record()
     pr.add_parent("Person")
     pr.add_property("lastname", lastname)