diff --git a/applications/test/IOobjectList/Test-IOobjectList.C b/applications/test/IOobjectList/Test-IOobjectList.C
index 40b1f42e7e4282b51eb52fd4f70e6935857f1f8c..38031bee7fde784d1b5d4af4d74fb18b76142736 100644
--- a/applications/test/IOobjectList/Test-IOobjectList.C
+++ b/applications/test/IOobjectList/Test-IOobjectList.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2017-2018 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -23,6 +23,7 @@ License
 
 Description
     Basic tests of IOobjectList
+
 \*---------------------------------------------------------------------------*/
 
 #include "argList.H"
@@ -34,13 +35,52 @@ Description
 
 using namespace Foam;
 
+void report(const IOobjectList& objects)
+{
+    Info<< "Names: " << flatOutput(objects.sortedNames()) << nl
+        << "Objects: " << objects << nl
+        << "----" << nl;
+}
+
+
+void reportDetail(const IOobjectList& objects)
+{
+    Info<<"Details:" << nl;
+
+    for (const word& key : objects.sortedNames())
+    {
+        IOobject* io = objects.lookup(key);
+
+        Info<< key << " (" << io->headerClassName()
+            << ") = addr " << long(io) << nl;
+    }
+
+    Info<<"====" << nl;
+}
+
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 // Main program:
 
 int main(int argc, char *argv[])
 {
     argList::noParallel();
-    argList::addOption("re", "wordRes");
+    argList::addOption
+    (
+        "filter",
+        "wordRes",
+        "filter keys with names or regexs"
+    );
+    argList::addBoolOption
+    (
+        "copy-append",
+        "test move append lists (requires -filter)"
+    );
+    argList::addBoolOption
+    (
+        "move-append",
+        "test move append lists (requires -filter)"
+    );
 
     // timeSelector::addOptions();
     timeSelector::addOptions(true, true);
@@ -49,11 +89,25 @@ int main(int argc, char *argv[])
     #include "createTime.H"
 
     wordRes matcher;
-    if (args.readListIfPresent<wordRe>("re", matcher))
+    if (args.readListIfPresent<wordRe>("filter", matcher))
     {
         Info<<"limit names: " << matcher << nl;
     }
 
+    if (args.found("copy-append") && matcher.empty())
+    {
+        FatalError
+            << nl << "The -copy-append test also requires -filter" << nl
+            << exit(FatalError);
+    }
+    if (args.found("move-append") && matcher.empty())
+    {
+        FatalError
+            << nl << "The -move-append test also requires -filter" << nl
+            << exit(FatalError);
+    }
+
+
     const hashedWordList subsetTypes
     {
         volScalarField::typeName,
@@ -79,9 +133,7 @@ int main(int argc, char *argv[])
 
         Info<< "Time: " << runTime.timeName() << nl;
 
-        Info<<"Name:    " << flatOutput(objects.sortedNames()) << nl
-            <<"Objects: " << objects << nl
-            <<"Classes: " << classes << nl;
+        report(objects);
 
         classes.filterKeys(subsetTypes);
         Info<<"only retain: " << flatOutput(subsetTypes) << nl;
@@ -91,6 +143,50 @@ int main(int argc, char *argv[])
         classes.erase(subsetTypes);
         Info<<"remove: " << flatOutput(subsetTypes) << nl;
         Info<<"Pruned: " << classes << nl;
+
+        // On last time
+        if (timeI == timeDirs.size()-1)
+        {
+            if (args.found("copy-append"))
+            {
+                Info<< nl << "Test move append" << nl;
+            }
+            else if (args.found("move-append"))
+            {
+                Info<< nl << "Test move append" << nl;
+            }
+            else
+            {
+                continue;
+            }
+
+            IOobjectList other(runTime, runTime.timeName());
+
+            Info<< "==original==" << nl; reportDetail(objects);
+
+            objects.filterKeys(matcher);
+
+            Info<< "==target==" << nl; reportDetail(objects);
+            Info<< "==source==" << nl; reportDetail(other);
+
+            if (args.found("copy-append"))
+            {
+                objects.append(other);
+
+                Info<< nl << "After copy-append" << nl;
+            }
+            else
+            {
+                objects.append(std::move(other));
+
+                Info<< nl << "After move-append" << nl;
+            }
+
+            Info<< "==target==" << nl; reportDetail(objects);
+            Info<< "==source==" << nl; reportDetail(other);
+
+            Info<< nl;
+        }
     }
 
     Info<< "\nEnd\n" << endl;
diff --git a/src/OpenFOAM/db/IOobjectList/IOobjectList.C b/src/OpenFOAM/db/IOobjectList/IOobjectList.C
index c8147464dfa8ff01369b98b1154e28257ee8134d..b96667dc82fc3df1be9aa2a39e6bdb76336b8584 100644
--- a/src/OpenFOAM/db/IOobjectList/IOobjectList.C
+++ b/src/OpenFOAM/db/IOobjectList/IOobjectList.C
@@ -298,6 +298,56 @@ bool Foam::IOobjectList::add(autoPtr<IOobject>&& objectPtr)
 }
 
 
+Foam::label Foam::IOobjectList::append(const IOobjectList& other)
+{
+    label count = 0;
+
+    forAllConstIters(other, iter)
+    {
+        if (!found(iter.key()))
+        {
+            if (IOobject::debug)
+            {
+                InfoInFunction << "Copy append " << iter.key() << nl;
+            }
+
+            set(iter.key(), new IOobject(*(iter.object())));
+            ++count;
+        }
+    }
+
+    return count;
+}
+
+
+Foam::label Foam::IOobjectList::append(IOobjectList&& other)
+{
+    // Remove by name to avoid uncertainties about invalid iterators
+
+    label count = 0;
+
+    wordList keys(other.toc());
+
+    for (const word& key : keys)
+    {
+        if (!found(key))
+        {
+            if (IOobject::debug)
+            {
+                InfoInFunction << "Move append " << key << nl;
+            }
+
+            if (add(other.remove(key)))
+            {
+                ++count;
+            }
+        }
+    }
+
+    return count;
+}
+
+
 bool Foam::IOobjectList::remove(const IOobject& io)
 {
     return erase(io.name());
@@ -317,15 +367,12 @@ Foam::IOobject* Foam::IOobjectList::lookup(const word& name) const
 
         return const_cast<IOobject*>(*iter);
     }
-    else
-    {
-        if (IOobject::debug)
-        {
-            InfoInFunction << "Could not find " << name << endl;
-        }
 
-        return nullptr;
+    if (IOobject::debug)
+    {
+        InfoInFunction << "Could not find " << name << endl;
     }
+    return nullptr;
 }
 
 
diff --git a/src/OpenFOAM/db/IOobjectList/IOobjectList.H b/src/OpenFOAM/db/IOobjectList/IOobjectList.H
index e1922945fcfcca1ec4cb359a0167df2c110c1958..f3d206d8506005eba226ee51ea6b4ed8cf8bd970 100644
--- a/src/OpenFOAM/db/IOobjectList/IOobjectList.H
+++ b/src/OpenFOAM/db/IOobjectList/IOobjectList.H
@@ -94,16 +94,34 @@ public:
 
     // Basic methods
 
-        //- Add an IOobject to the list
+        //- Add IOobject to the list
         bool add(autoPtr<IOobject>& objectPtr);
 
-        //- Add an IOobject to the list
+        //- Add IOobject to the list
         bool add(autoPtr<IOobject>&& objectPtr);
 
-        //- Remove an IOobject from the list, by iterator
+        //- Copy append objects from other to this list, but do not overwrite
+        //- existing keys.
+        //
+        //  \return number of items added
+        label append(const IOobjectList& other);
+
+        //- Move append objects from other to this list, but do not overwrite
+        //- existing keys.
+        //  After calling this, the other parameter will contains any items
+        //  that could not be moved.
+        //
+        //  \return number of items added
+        label append(IOobjectList&& other);
+
+        //- Remove IOobject from the list, by name or by iterator.
+        //
+        //  \return autoPtr<IOobject>
         using HashPtrTable<IOobject>::remove;
 
-        //- Remove an IOobject from the list
+        //- Remove IOobject from the list.
+        //
+        //  \return True if object was removed
         bool remove(const IOobject& io);