diff --git a/doc/manual/source/running-dynare.rst b/doc/manual/source/running-dynare.rst
index bb69284af05eaf3db484029a23698e884c95694c..076d9ec780bdc3f4a3326ea589af5a1f3b502708 100644
--- a/doc/manual/source/running-dynare.rst
+++ b/doc/manual/source/running-dynare.rst
@@ -334,9 +334,10 @@ by the ``dynare`` command.
         Defines a macro-variable from the command line (the same effect as
         using the Macro directive ``@#define`` in a model file, see
         :ref:`macro-proc-lang`). Note that when passing a MACRO_EXPRESSION that
-        contains a space, you must surround the entire ``-D`` flag with single
-        quotes, as in the following example. Also note that an expression
-        passed on the command line can reference variables defined before it.
+        contains a space (or, under Octave, a double quote), you must surround
+        the entire ``-D`` flag with single quotes, as in the following example.
+        Also note that an expression passed on the command line can reference
+        variables defined before it.
 
         *Example*
 
diff --git a/matlab/dynare.m b/matlab/dynare.m
index d429d54c22dd7fda8a444523265d050eb99cdfce..9370ca06e0bf763f43f63502517d543649220fa5 100644
--- a/matlab/dynare.m
+++ b/matlab/dynare.m
@@ -210,32 +210,32 @@ else
     end
 end
 
-command = ['"' dynareroot 'preprocessor' arch_ext filesep 'dynare_m" ' fname] ;
-command = [ command ' mexext=' mexext ' "matlabroot=' matlabroot '"'];
-if ~isempty(varargin)
-    if ispc
-        varargincopy = varargin;
-        for i = 1:length(varargincopy)
-            if varargincopy{i}(end) == '\'
-                varargincopy{i} = [varargincopy{i} '\'];
-            end
-        end
-        varargincopy = strrep(varargincopy, '"', '\"');
-        dynare_varargin = ['"' strjoin(varargincopy, '" "') '"'];
-    else
-        dynare_varargin = ['''' strjoin(varargin, ''' ''') ''''];
-    end
-    command = [command ' ' dynare_varargin];
-end
-
 if preprocessoroutput
     fprintf(['Starting Dynare (version ' dynare_version() ').\n']);
     fprintf('Calling Dynare with arguments: ');
     if isempty(varargin)
         disp('none')
     else
-        disp(dynare_varargin);
+        disp(strjoin(varargin, ' '));
+    end
+end
+
+command = ['"' dynareroot 'preprocessor' arch_ext filesep 'dynare_m" ' fname] ;
+command = [ command ' mexext=' mexext ' "matlabroot=' matlabroot '"'];
+% Properly quote arguments before passing them to the shell
+if ~isempty(varargin)
+    varargincopy = varargin;
+    % Escape backslashes and double-quotes
+    varargincopy = strrep(varargincopy, '\', '\\');
+    varargincopy = strrep(varargincopy, '"', '\"');
+    if ~ispc
+        % On GNU/Linux and macOS, also escape dollars and backquotes
+        varargincopy = strrep(varargincopy, '$', '\$');
+        varargincopy = strrep(varargincopy, '`', '\`');
     end
+    % Finally, enclose arguments within double quotes
+    dynare_varargin = ['"' strjoin(varargincopy, '" "') '"'];
+    command = [command ' ' dynare_varargin];
 end
 
 % Under Windows, make sure the MEX file is unloaded (in the use_dll case),