diff --git a/applications/test/argList/Test-argList.C b/applications/test/argList/Test-argList.C
index ac62fce0ba7c20e98217c86cd7102e354e02fc3a..f36ac730a0915532646393a538e9e2c985e59bb7 100644
--- a/applications/test/argList/Test-argList.C
+++ b/applications/test/argList/Test-argList.C
@@ -40,7 +40,6 @@ int main(int argc, char *argv[])
     argList::noBanner();
     argList::noParallel();
     // argList::noFunctionObjects();
-    argList::removeOption("case");
     argList::addOption("label",  "value", "Test parsing of label");
     argList::addOption("scalar", "value", "Test parsing of scalar");
     argList::addOption("string", "value", "Test string lookup");
@@ -73,6 +72,15 @@ int main(int argc, char *argv[])
 
     argList args(argc, argv, false, true);
 
+    Info<< "command-line ("
+        << args.options().size() << " options, "
+        << args.args().size() << " args)" << nl
+        << "    " << args.commandLine().c_str() << nl << nl;
+
+    Info<< "rootPath:   " << args.rootPath() << nl
+        << "globalCase: " << args.globalCaseName() << nl
+        << "globalPath: " << args.globalPath() << nl
+        << nl;
 
     Info<<"have: "
         <<args.count({"label", "scalar"}) << " options" << nl;
diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C
index acb268e37ffb824665a0ab41a39d917113c7b710..92ac5235d412d9469f1c86c254308c35480f7d26 100644
--- a/src/OpenFOAM/global/argList/argList.C
+++ b/src/OpenFOAM/global/argList/argList.C
@@ -706,72 +706,59 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv)
     args_.resize(nArgs);
 
     std::string::size_type len = (nArgs-1); // Spaces between args
-    forAll(args_, argi)
+    for (const auto& s : args_)
     {
-        len += args_[argi].size();
+        len += s.length();
     }
 
     // Length needed for regrouped command-line
-    argListStr_.reserve(len);
+    commandLine_.reserve(len);
 
     return nArgs < argc;
 }
 
 
-void Foam::argList::getRootCase()
+void Foam::argList::setCasePaths()
 {
-    fileName casePath;
+    fileName caseDir;
 
-    // [-case dir] specified
-    const auto optIter = options_.cfind("case");
+    const auto optIter = options_.cfind("case");  // [-case dir] specified?
 
     if (optIter.found())
     {
-        casePath = optIter.object();
-        casePath.clean();
+        caseDir = optIter.object();
+        caseDir.clean();
 
-        if (casePath.empty() || casePath == ".")
+        if (caseDir.empty() || caseDir == ".")
         {
-            // Handle degenerate form and '-case .' like no -case specified
-            casePath = cwd();
+            // Treat "", "." and "./" as if -case was not specified
+            caseDir = cwd();
             options_.erase("case");
         }
-        else if (!casePath.isAbsolute() && casePath.name() == "..")
+        else if (!caseDir.isAbsolute())
         {
-            // Avoid relative cases ending in '..' - makes for very ugly names
-            casePath = cwd()/casePath;
-            casePath.clean();
+            caseDir = cwd()/caseDir;
+            caseDir.clean();
         }
     }
     else
     {
         // Nothing specified, use the current dir
-        casePath = cwd();
+        caseDir = cwd();
     }
 
-    rootPath_   = casePath.path();
-    globalCase_ = casePath.name();
-    case_       = globalCase_;
+    // The caseDir is a cleaned, absolute path
 
-    // The name of the executable, unless already present in the environment
-    setEnv("FOAM_EXECUTABLE", executable_, false);
+    rootPath_   = caseDir.path();
+    globalCase_ = caseDir.name();
+    case_       = globalCase_;  // The (processor) local case name
 
-    // Set the case and case-name as an environment variable
-    if (rootPath_.isAbsolute())
-    {
-        // Absolute path - use as-is
-        setEnv("FOAM_CASE", rootPath_/globalCase_, true);
-        setEnv("FOAM_CASENAME", globalCase_, true);
-    }
-    else
-    {
-        // Qualify relative path
-        casePath = cwd()/rootPath_/globalCase_;
-        casePath.clean();
+    // Global case (directory) and case-name as environment variables
+    setEnv("FOAM_CASE", caseDir, true);
+    setEnv("FOAM_CASENAME", globalCase_, true);
 
-        setEnv("FOAM_CASE", casePath, true);
-        setEnv("FOAM_CASENAME", casePath.name(), true);
-    }
+    // Executable name, unless already present in the environment
+    setEnv("FOAM_EXECUTABLE", executable_, false);
 }
 
 
@@ -837,7 +824,7 @@ Foam::argList::argList
 
     // Convert argv -> args_ and capture ( ... ) lists
     regroupArgv(argc, argv);
-    argListStr_ += args_[0];
+    commandLine_ += args_[0];
 
     // Set executable name immediately - useful when emitting errors.
     executable_ = fileName(args_[0]).name();
@@ -846,8 +833,8 @@ Foam::argList::argList
     int nArgs = 1;
     for (int argi = 1; argi < args_.size(); ++argi)
     {
-        argListStr_ += ' ';
-        argListStr_ += args_[argi];
+        commandLine_ += ' ';
+        commandLine_ += args_[argi];
 
         if (args_[argi][0] == '-')
         {
@@ -881,8 +868,8 @@ Foam::argList::argList
                     Pstream::exit(1); // works for serial and parallel
                 }
 
-                argListStr_ += ' ';
-                argListStr_ += args_[argi];
+                commandLine_ += ' ';
+                commandLine_ += args_[argi];
                 // Handle duplicates by taking the last -option specified
                 options_.set(optName, args_[argi]);
             }
@@ -926,7 +913,7 @@ Foam::argList::argList
     rootPath_(args.rootPath_),
     globalCase_(args.globalCase_),
     case_(args.case_),
-    argListStr_(args.argListStr_)
+    commandLine_(args.commandLine_)
 {
     parse(checkArgs, checkOpts, initialise);
 }
@@ -1013,7 +1000,7 @@ void Foam::argList::parse
                 #endif
                 << nl
                 << "Arch   : " << Foam::FOAMbuildArch << nl
-                << "Exec   : " << argListStr_.c_str() << nl
+                << "Exec   : " << commandLine_.c_str() << nl
                 << "Date   : " << dateString.c_str() << nl
                 << "Time   : " << timeString.c_str() << nl
                 << "Host   : " << hostName().c_str() << nl
@@ -1025,7 +1012,7 @@ void Foam::argList::parse
         jobInfo.add("userName", userName());
         jobInfo.add("foamVersion", word(Foam::FOAMversion));
         jobInfo.add("code", executable_);
-        jobInfo.add("argList", argListStr_);
+        jobInfo.add("argList", commandLine_);
         jobInfo.add("currentDir", cwd());
         jobInfo.add("PPID", ppid());
         jobInfo.add("PGID", pgid());
@@ -1128,7 +1115,7 @@ void Foam::argList::parse
         if (Pstream::master())
         {
             // Establish rootPath_/globalCase_/case_ for master
-            getRootCase();
+            setCasePaths();
 
             // Establish location of decomposeParDict, allow override with
             // the -decomposeParDict option.
@@ -1288,9 +1275,9 @@ void Foam::argList::parse
                         << exit(FatalError);
                 }
 
-                forAll(roots, i)
+                for (fileName& dir : roots)
                 {
-                    roots[i].expand();
+                    dir.expand();
                 }
 
                 // Distribute the master's argument list (with new root)
@@ -1330,8 +1317,8 @@ void Foam::argList::parse
                     (
                         isDir
                         (
-                            rootPath_/globalCase_/"processor"
-                          + name(++nProcDirs)
+                            rootPath_/globalCase_
+                          / "processor" + Foam::name(++nProcDirs)
                         )
                     )
                     {}
@@ -1371,19 +1358,20 @@ void Foam::argList::parse
             fromMaster >> args_ >> options_ >> distributed_;
 
             // Establish rootPath_/globalCase_/case_ for slave
-            getRootCase();
+            setCasePaths();
         }
 
         nProcs = Pstream::nProcs();
-        case_ = globalCase_/(word("processor") + name(Pstream::myProcNo()));
+        case_ = globalCase_/("processor" + Foam::name(Pstream::myProcNo()));
     }
     else
     {
         // Establish rootPath_/globalCase_/case_
-        getRootCase();
-        case_ = globalCase_;
+        setCasePaths();
+        case_ = globalCase_;   // Redundant, but extra safety?
     }
 
+
     // Keep or discard slave and root information for reporting:
     if (Pstream::master() && parRunControl_.parRun())
     {
diff --git a/src/OpenFOAM/global/argList/argList.H b/src/OpenFOAM/global/argList/argList.H
index b319b5e165ec3ea297bcb7c0e985886d7246a114..d55219e7857a9bd4bc690fc46be234ddcbf66d41 100644
--- a/src/OpenFOAM/global/argList/argList.H
+++ b/src/OpenFOAM/global/argList/argList.H
@@ -143,7 +143,9 @@ class argList
         bool distributed_;
         fileName globalCase_;
         fileName case_;
-        string argListStr_;
+
+        //- The command line options and arguments concatenated as a string
+        string commandLine_;
 
 
     // Private Member Functions
@@ -176,14 +178,14 @@ class argList
         template<class T>
         static inline void readList(ITstream& is, List<T>& list);
 
-        //- Get rootPath_ / globalCase_ from one of the following forms
+        //- Set rootPath_, globalCase_, case_ from one of the following forms
         //   * [-case dir]
         //   * cwd
         //
         // Also export FOAM_CASE and FOAM_CASENAME environment variables
         // so they can be used immediately (eg, in decomposeParDict), as well
         // as the FOAM_EXECUTABLE environment.
-        void getRootCase();
+        void setCasePaths();
 
         //- Transcribe argv into internal args_.
         //  Transform sequences with "(" ... ")" into string lists
@@ -280,6 +282,9 @@ public:
         //- Name of executable without the path
         inline const word& executable() const;
 
+        //- The command line options and arguments concatenated as a string
+        inline const string& commandLine() const;
+
         //- Return root path
         inline const fileName& rootPath() const;
 
@@ -296,10 +301,12 @@ public:
         //- Return parRunControl
         inline const ParRunControl& parRunControl() const;
 
-        //- Return the path to the caseName
+        //- Return the full path to the (processor local) case
+        //  \note This is guaranteed to be an absolute path
         inline fileName path() const;
 
-        //- Return the path to the globalCaseName
+        //- Return the full path to the global case
+        //  \note This is guaranteed to be an absolute path
         inline fileName globalPath() const;
 
         //- Return the number of arguments
diff --git a/src/OpenFOAM/global/argList/argListI.H b/src/OpenFOAM/global/argList/argListI.H
index c473becff175d198ede8c035cf1e6991aa350dfc..2848add5077ba7c0466de45c6c5fe0fab2fdfdb7 100644
--- a/src/OpenFOAM/global/argList/argListI.H
+++ b/src/OpenFOAM/global/argList/argListI.H
@@ -51,6 +51,12 @@ inline const Foam::word& Foam::argList::executable() const
 }
 
 
+inline const Foam::string& Foam::argList::commandLine() const
+{
+    return commandLine_;
+}
+
+
 inline const Foam::fileName& Foam::argList::rootPath() const
 {
     return rootPath_;