7

This is probably too easy, but I cannot google the answer for this: how can I get command line arguments in matlab script.

I run matlab as matlab -nodisplay -r "run('script.m')" and I want to return all arguments as a list. Something similar to python sys.argv. How can I do this?

I'm using Linux Mint and MATLAB 2015a.

Sergey Ivanov
  • 3,719
  • 7
  • 34
  • 59
  • Perhaps you can make an example of what exactly you want to get for those unfamiliar with the functionality you refer to in python? – Dennis Jaheruddin Jun 12 '15 at 12:20
  • Usually, arguments can be accepted or passed, not returned. What do you mean after the arguments here? Do you mean values of the function or you want to pass arguments inside? – freude Jun 12 '15 at 12:21
  • If you want an example of how to call matlab from the command line, you can check out [this question](http://stackoverflow.com/questions/18204663/run-a-script-that-uses-multiple-matlab-sessions). – Dennis Jaheruddin Jun 12 '15 at 12:22
  • No, I just want from `matlab` access all command line arguments. In this example, I want to retrieve as a matrix [`-nodisplay`, `-r`, `"run('script.m')"`] – Sergey Ivanov Jun 12 '15 at 12:25
  • In fact, I want to pass some additional arguments at the end of command and I want to access those arguments from the script. – Sergey Ivanov Jun 12 '15 at 12:26
  • Are you using Windows or Linux? – Rafael Monteiro Jun 12 '15 at 13:19
  • Perhaps you can give an example including the sorts of arguments you would give (in a realistic case) and what the result would look like (probably a cell array, not an array). – TheBlackCat Jun 12 '15 at 13:22
  • @RafaelMonteiro That really shouldn't matter. – TheBlackCat Jun 12 '15 at 13:22
  • @TheBlackCat I just want to provide the name of the file. That's it. Then in the script I want to open that file and read its content (it's just one column). – Sergey Ivanov Jun 12 '15 at 13:24
  • @TheBlackCat I was thinking of a mex solution, hence the question. Another option would be to parse WMIC output, but that would only work on Windows (that WOULD work, I tested here). – Rafael Monteiro Jun 12 '15 at 13:24

2 Answers2

4

I came up with a simple function that works on both Windows and Linux (Ubuntu):

function args = GetCommandLineArgs()

if isunix
    fid = fopen(['/proc/' num2str(feature('getpid')) '/cmdline'], 'r');
    args = textscan(fid, '%s', 'Delimiter', char(0));
    fclose(fid);
else
    kernel32WasAlreadyLoaded = libisloaded('kernel32');
    if ~kernel32WasAlreadyLoaded
        temporaryHeaderName = [gettempfolder '\GetCommandLineA.h'];
        dlmwrite(temporaryHeaderName, 'char* __stdcall GetCommandLineA(void);', '');
        loadlibrary('kernel32', temporaryHeaderName);
        delete(temporaryHeaderName);
    end
    args = textscan(calllib('kernel32', 'GetCommandLineA'), '%q');
    if ~kernel32WasAlreadyLoaded
        unloadlibrary kernel32;
    end
end

args = args{1};

On your sample call, it would return this:

>> GetCommandLineArgs

args = 

    '/[path-to-matlab-home-folder]/'
    '-nodisplay'
    '-r'
    'run('script.m')'

It returns a cell array of strings, where the first string is the path to MATLAB home folder (on Linux) or the full path to MATLAB executable (on Windows) and the others are the program arguments (if any).

How it works:

  • On Linux: the function gets the current Matlab process ID using the feature function (be aware it's an undocumented feature). And reads the /proc/[PID]/cmdline file, which on Linux gives the command line arguments of any process. The values are separated by the null character \0, hence the textscan with delimiter = char(0).

  • On Windows: the function calls GetCommandLineA, which returns the command line arguments on a string. Then it uses textscan to split the arguments on individual strings. The GetCommandLineA function is called using MATLAB's calllib. It requires a header file. Since we only want to use one function, it creates the header file on the fly on the temporary folder and deletes it after it's no longer needed. Also the function takes care not to unload the library in case it was already loaded (for example, if the calling script already loads it for some other purpose).

Community
  • 1
  • 1
Rafael Monteiro
  • 4,509
  • 1
  • 16
  • 28
3

I am not aware of a direction solution (like an inbuilt function). However, you can use one of the following workarounds:

1. method

This only works in Linux:

Create a file pid_wrapper.m with the following contents:

function [] = pid_wrapper( parent_pid )

[~, matlab_pid] = system(['pgrep -P' num2str(parent_pid)]);
matlab_pid = strtrim(matlab_pid);
[~, matlab_args] = system(['ps -h -ocommand ' num2str(matlab_pid)]);
matlab_args = strsplit(strtrim(matlab_args));
disp(matlab_args);

% call your script with the extracted arguments in matlab_args
% ...

end

Invoke MATLAB like this:

matlab -nodisplay -r "pid_wrapper($$)"

This will pass the process id of MATLAB's parent process (i.e. the shell which launches MATLAB) to wrapper. This can then be used to find out the child MATLAB process and its command line arguments which you then can access in matlab_args.

2. method

This method is OS independent and does not really find out the command line arguments, but since your goal is to pass additional parameters to a script, it might work for you.

Create a file vararg_wrapper.m with the following contents:

function [] = wrapper( varargin )

% all parameters can be accessed in varargin
for i=1:nargin
    disp(varargin{i});
end

% call your script with the supplied parameters 
% ...

end

Invoke MATLAB like this:

matlab -nodisplay -r "vararg_wrapper('first_param', 'second_param')"

This will pass {'first_param', 'second_param'} to vararg_wrapper which you can then forward to your script.

m.s.
  • 16,063
  • 7
  • 53
  • 88