diff --git a/src/OpenFOAM/db/Time/TimeIO.C b/src/OpenFOAM/db/Time/TimeIO.C
index 1b9232392ce4fbd305f3fd0d0d0a60e5021185f3..1a57de375c9182ba49d4aec4961ccd1fdd535d82 100644
--- a/src/OpenFOAM/db/Time/TimeIO.C
+++ b/src/OpenFOAM/db/Time/TimeIO.C
@@ -166,8 +166,17 @@ void Foam::Time::readDict()
         }
         controlDict_.watchIndices().clear();
 
+        // The new handler, with verbosity
+        autoPtr<fileOperation> newHandler =
+            fileOperation::New(fileHandlerName, true);
+
+        if (TimePaths::distributed() && newHandler)
+        {
+            newHandler->distributed(true);
+        }
+
         // Installing the new handler
-        Foam::fileHandler(fileOperation::New(fileHandlerName, true));
+        Foam::fileHandler(std::move(newHandler));
 
         // Reinstall old watches
         fileHandler().addWatches(controlDict_, oldWatched);
diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C
index 735a2487c97d223c7d59af2a9738b0ee143a0059..2e1d2fc48d8e810c1fcf2f8be8038cada38ba15a 100644
--- a/src/OpenFOAM/global/argList/argList.C
+++ b/src/OpenFOAM/global/argList/argList.C
@@ -1414,6 +1414,14 @@ void Foam::argList::parse
         case_ = globalCase_;   // Redundant, but extra safety?
     }
 
+    // If needed, adjust fileHandler for distributed roots
+    if (parRunControl_.distributed())
+    {
+        if (fileOperation::fileHandlerPtr_)
+        {
+            fileOperation::fileHandlerPtr_->distributed(true);
+        }
+    }
 
     // Keep or discard slave and root information for reporting:
     if (Pstream::master() && parRunControl_.parRun())
diff --git a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
index 4ee216eb7b39bf363a3a65efd0659a28fee9633a..fa5345096d74823f9189b89f1b520d19963e3f25 100644
--- a/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
+++ b/src/OpenFOAM/global/fileOperations/fileOperation/fileOperation.C
@@ -361,21 +361,62 @@ Foam::fileOperation::lookupAndCacheProcessorsPath
             return iter.val();
         }
 
+        DynamicList<dirIndex> procDirs;
+        fileNameList dirEntries;
+
         // Read all directories to see any beginning with processor
         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-        DynamicList<dirIndex> procDirs;
-
         // Note: use parallel synchronised reading so cache will be same
         //       order on all processors
-        fileNameList dirNames(readDir(path, fileName::Type::DIRECTORY));
+
+        const bool readDirMasterOnly
+        (
+            regIOobject::fileModificationChecking == IOobject::timeStampMaster
+         || regIOobject::fileModificationChecking == IOobject::inotifyMaster
+        );
+
+        // As byproduct of the above selection, we exclude masterUncollated
+        // from using read/send, but that doesn't matter since that is what
+        // its own internals for readDir() do anyhow.
+
+        if (readDirMasterOnly && Pstream::parRun() && !distributed())
+        {
+            // Non-distributed.
+            // Read on master only and send to subProcs
+
+            if (Pstream::master())
+            {
+                dirEntries = Foam::readDir(path, fileName::Type::DIRECTORY);
+
+                DebugInfo
+                    << "readDir on master: send " << dirEntries.size()
+                    << " names to sub-processes" << endl;
+            }
+
+            Pstream::scatter(dirEntries, Pstream::msgType(), comm_);
+        }
+        else
+        {
+            // Serial or distributed roots.
+            // Handle readDir() with virtual method
+
+            if (debug)
+            {
+                Pout<< "readDir without special master/send treatment"
+                    << endl;
+            }
+
+            dirEntries = readDir(path, fileName::Type::DIRECTORY);
+        }
+
 
         // Extract info from processorsDDD or processorDDD:
         // - highest processor number
         // - directory+offset containing data for proci
         label maxProc = -1;
 
-        for (const fileName& dirN : dirNames)
+        for (const fileName& dirN : dirEntries)
         {
             // Analyse directory name
             fileName rp, rd, rl;
@@ -775,16 +816,11 @@ Foam::instantList Foam::fileOperation::findTimes
             << directory << endl;
     }
 
-    // Read directory entries into a list
-    fileNameList dirEntries
-    (
-        Foam::readDir
-        (
-            directory,
-            fileName::DIRECTORY
-        )
-    );
+    // Note: do NOT use master-only reading here (as per lookupProcessorsPath)
+    // since this routine is called on an individual processorN directory
 
+    // Read directory entries into a list
+    fileNameList dirEntries(Foam::readDir(directory, fileName::DIRECTORY));
     instantList times = sortTimes(dirEntries, constantName);
 
 
@@ -1269,7 +1305,6 @@ Foam::label Foam::fileOperation::splitProcessorPath
             // We are done!
             break;
         }
-
     }
 
     if (pos != string::npos)