Mike on the MATLAB Desktop

May 17th, 2010

Calling Shell Commands from MATLAB

I’ve written before about accessing Java from the Command Line, but you can also make calls into other systems from MATLAB. For example, you can access libraries written in C/C++ or Fortran, connect to .NET processes (on Windows), and make calls to a system shell. Today I will discuss the different ways you can run a system shell command:

  • system: The system function will execute a command in your OS shell and return the execution status (generally 0 for success and 1 for an error). For example:
    s = system('dir')
     Volume in drive H is mkatz
     Volume Serial Number is 0702-7BA0 
    
     Directory of h:\www\blog\java 
    
    05/17/2010  09:22 AM    <DIR>          .
    04/19/2010  08:27 AM    <DIR>          ..
    07/02/2009  01:10 PM                51 parsedouble.m
    05/17/2010  09:43 AM    <DIR>          wordpress_html
    07/02/2009  03:49 PM                85 inmemex.m
    07/02/2009  04:04 PM                31 tmp.m
    07/08/2009  08:02 AM               154 swing.m
    07/10/2009  09:39 AM               134 size_listen.m
    08/17/2009  01:43 PM               593 m3m.m
    04/26/2010  08:26 AM               146 heap_size.m
    04/26/2010  08:29 AM                44 maxmem.m
    05/17/2010  09:22 AM                17 system_commands.m
                   9 File(s)          1,255 bytes
                   3 Dir(s)   8,975,208,448 bytes free 
    
    s =
    
         0
    

    The nice thing about the system function is that it is platform independent, which means if you don’t care where your code will run and the command it will issue is the same, you can reuse this function. Note that system is platform-independent, but the system commands you run using this are likely to be very dependent on your OS. If you have platform-specific code, the isunix, ispc, ismac, and computer functions will allow you to programmatically determine what operating system the program is running on.

  • There’s also the !, or exclamation point operator. This is symbol is sometimes also known as “bang” or “hey there”, and it’s just a shorthand for the above mentioned system operation. The “!” operation is quick an easy, but can’t be used to take functional arguments. Because we Tab-complete filenames with system operations, a dirty trick to complete file paths from the command line is to stick a “!” at the start of the line, write out a normal MATLAB expression and then delete the “!” when you’re done.

With either of these functions, there are a few things to keep in mind. By default they will pause the MATLAB execution until the system command exits. If you just want to kick off a separate system process and have MATLAB continue, append an ampersand (“&”) to the end of the command. Also, if you want to capture the output of a system command as a string, wrap the call as an input to the evalc function:

s = evalc('system(''dir'')')
s =

 Volume in drive H is mkatz
 Volume Serial Number is 0702-7BA0 

 Directory of h:\www\blog\java 

05/17/2010  09:22 AM    <DIR>          .
04/19/2010  08:27 AM    <DIR>          ..
07/02/2009  01:10 PM                51 parsedouble.m
05/17/2010  10:03 AM    <DIR>          wordpress_html
07/02/2009  03:49 PM                85 inmemex.m
07/02/2009  04:04 PM                31 tmp.m
07/08/2009  08:02 AM               154 swing.m
07/10/2009  09:39 AM               134 size_listen.m
08/17/2009  01:43 PM               593 m3m.m
04/26/2010  08:26 AM               146 heap_size.m
04/26/2010  08:29 AM                44 maxmem.m
05/17/2010  10:03 AM                28 system_commands.m
               9 File(s)          1,266 bytes
               3 Dir(s)   8,975,208,448 bytes free

There are also platform-specificthese system commands: dos and unix. However, these commands are exactly the same as system. If I had to guess, we’ve probably been keeping them around for compatibility reasons.

My personal favorite of all of these is winopen which is Windows-only, and it’s basically what you would get if you typed the input command in the Run box of the Start menu. I use this command all the time to open a path in an explorer window, like so:

winopen(pwd)

Matt Dunham at the Advanced MATLAB blog wrote a nice post awhile back about a whole range of systems that you can access from the MATLAB commands, and expands on some of the concepts presented here.

34 Responses to “Calling Shell Commands from MATLAB”

  1. Pekka Kumpulainen replied on :

    Why would you use evalc to capture the output?
    Wouldn’t this do the same?
    [status, result] = system(‘dir’);

  2. Mike replied on :

    Why, yes that would.

  3. Eric M. replied on :

    I have run into some issues with running executables (.exe) from within Matlab using the system command, especially when the data from the executable is written to an output file that is going to be read into Matlab. It appears to be something with the timing in that when trying to read the output, the file is not complete. The only way I have found to remedy the issue is to put the system command in a while loop like this:

        count = 1;
        result = 0;
        while ~isempty(result) && count<=5
            [status, result] = system('MODTRAN.exe');
            count = count+1;
        end
    

    Any guidance for a more elegant solution?

  4. matt fig replied on :

    winopen(pwd)

    Oh man, THANK YOU! I should have thought of this nice solution long ago. Live and learn.

  5. Mike replied on :

    @Eric,

    That is quite possible in regard to file i/o. That’s a tough one. Is there something about the file you could poll for? Do you have to call the executable multiple times, or can just use PAUSE?

  6. Eric M. replied on :

    @Mike,
    I suppose I could poll the file, but to me, that seemed even less elegant than what I chose to do. The reason I had to implement this way is that SOMETIMES it works on the first call. Typically the function containing this call is called in a loop and without the while loop, it fails at random points within the loop.

    Pause works sometimes but I thought it was overkill since sometimes the pause is not needed.

    Oh well. This seems to work but not as elegant as I like.

  7. NickS replied on :

    I wanted to make a linux alternative for

    winopen

    , using the code:

    system(['xdg-open ' regexprep(folder, ' ', '\\ ')])
    

    where folder is the path to the folder. xdg-open should open the folder in the default file browser.

    regexprep

    is used to replace white spaces with ‘\ ‘ to prevent errors. However, upon executing this command, I receive the following error:

    nautilus: /home/nick/sys/os/glnx86/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by /usr/lib/libexempi.so.3)

    The same error arises when using the ‘nautilus’ command. Any idea how to solve this?

  8. Mike replied on :

    @NickS,

    Is it a path or environment variable issue? You might have to set those before calling the nautilus command.

  9. NickS replied on :

    @Mike

    I solved the problem. I just removed the dynamic link to libstdc++.so.6 and now it works just perfect. I am using Ubuntu Linux 10.04.

  10. OysterEngineer replied on :

    Why doesn’t the & show up in the documentation along with the list of special characters?

    What is this nautilus command?

  11. Mike replied on :

    @OysterEngineer,

    It’s not a MATLAB Command, it’s a shell directive(?) to run the command in the background.

  12. Chuck replied on :

    Is there any way to maintain continuity between shell calls (in UNIX?). I have some setup I need to do before the command I really want can be executed. The setup takes time, so I’d like to just do it once so I can then call my desired command over and over quickly.

    As an example of what I mean though:

    unix('setenv BOB abc;echo $BOB')
    

    says ‘abc’, but

    unix('setenv BOB abc')
    unix('echo $BOB')
    

    says BOB is undefined. It’s like it creates a new shell each time from scratch. Any solution?

  13. Mike replied on :

    @Chuck,
    Each call to unix is going to be a separate shell. You can set your environment in an init file, like a .cshrc. Alternatively you can write a batch script that runs all the commands once.

  14. Boris replied on :

    Hi Mike

    I have a little shortcut that launches a windows explorer in the current path, “pwd”. I’m on a Windows Vista x64 machine and the code i’m using is

    system(['%SystemRoot%\explorer /e,',pwd,',select,',pwd,'''']);
    

    The only catch is the command window becomes unresponsive until i kill the launched explorer window, even then i have to apply a few Ctrl-C’s to get things going sometimes. Any ideas how to make this system call work?
    The good news is that it appears that the following code snippet seems to work fine:

    p=java.io.File(pwd);
    jd=java.awt.Desktop.getDesktop;
    jd.browse(p.toURI)
    

    Boris

  15. Mike replied on :

    @Boris,

    I haven’t tried winopen(pwd) on Vista, but I assume it should still work? As for returning control back to MATLAB, just tack on a “ &” at the end of the system command.

  16. Boris replied on :

    @Mike

    Didnt even think of trying winopen(pwd), but that seems to work perfectly as well! So it looks like either winopen or the JAVA soln work fine. The problem i had with the “&” in the system call is that it launches a DOS window which i didnt want. Thanks mate.

  17. niko replied on :

    On OSX, winopen is replaced by “open”

    Gnome: gnome-open
    KDE: kde-open

    These commands are available for almost any desktop environment.

  18. Mike replied on :

    @niko,

    As system commands, you mean? E.g.

     system(['open ' pwd]);
    

    or,

     system(['kde-open ' pwd]);
    
  19. Gerrit replied on :

    One problem with the system-command is if I have special characters in my filename. The shell will interpret *, ;, [, ], ‘, “, etc. Is there any alternative to system that calls a process without calling the shell, or a function that escapes all special shell characters so it is safe to pass to system?

  20. Ike replied on :

    @Gerrit, what environment are you in? My suggestion may be different for WinXP/Cygwin shell from one for Linux/bash….

  21. Varuna De Silva replied on :

    Hi Mike,
    For a project of mine, I need to open a file with windows media player (not mmplayer) and then once it starts playing, I need to do some other tasks in matlab.

    I tried with the System() command but it does not return the control until it is finish playing.

    Is there any way that I can work around this. Any help is much appreciated.

  22. Mike replied on :

    @Varuna,

    Append a ” &” to the end of your command.

  23. Azwok replied on :

    Hi Mike,
    I am using system() to call python scripts and it has been working fine when running matlab in the GUI, and in -nodisplay mode. However I have recently encountered a situation where I receive an Assertion failed error:

    Assertion failed: Forced Assertion at line 320 of file “bnterm/bang.cpp”.
    pty[222]: tcsetattr [5] Input/output error

    This error occurrs when I use python to open and run matlab as a subprocess, this error is repeatable and always fails on the use of a system() command. Do you have any suggestions why the system() command stops working in this situation?

    Kind regards

  24. Azwok replied on :

    Apologies for the double post,
    I have actually just found a solution to my problem although still unsure why it fails in this situation.
    To prevent the Assertion failure I now have to run the python script that calls the matlab file in the background (using &). Since making this change I have not received an assertion failure on several tests.

    Cheers

  25. Don Krieger replied on :

    Hi,

    I am using an instance of Matlab as a slave by running the following short routine:
    while 1 > 0
    [status,result] = system(‘./DoTheWork.csh abc’)
    run MFileMadeByDoTheWork
    end

    I would like to pass at least one parameter to DoTheWork.csh in the system() call but haven’t figured out how to do variable substitution, i.e. I want abc to to be something that is assigned a value in MFileMadeByDoTheWork . I’m sure there’s some simple and obvious syntax rule but can’t find it.

    It would be very helpful if someone could provide me the proper assignment statement to use in the M-File,
    e.g.: abc = 3
    and the proper syntax to use in the system call to get it to pass the value of abc to the shell script. Thanks for your help and direction.

    Don

  26. Daniel Armyr replied on :

    I think this is what you are looking for:
    arg = ‘abc’;
    [status,result] = system(sprintf(’./DoTheWork.csh %s’, arg) );

  27. Daniel Armyr replied on :

    Or, if the argument should be a number:
    arg = 3;
    [status,result] = system(sprintf(’./DoTheWork.csh %f’, arg) );

  28. Don Krieger replied on :

    Thanks very much. That’s what I need.

    This allows me to take advantage of Matlab toolbox routines without having Matlab as the central element in my programming environment. By spawning a slave, I avoid the high cost of repeatedly starting Matlab. And using Matlab synchronously makes the programming very simple.

    Thanks again – don

  29. Jim replied on :

    Hi,

    I am using a Matlab GUI, in which system is called to execute an executable, tool.exe.

    tool.exe will run but will wait for an input to continue the process. Otherwise it will stay there waiting for the input from user. If running tool.exe in cmd shell, it will display the instructions when it’s ready to take the external input so I know when to do that.

    However, when running with system in Matlab GUI, it seems the shell with hang there without displaying the information for user to input. it seems the SYSTEM will only display the output when an executable finishes running. This seems to be my problem.

    I cannot run tool.exe at background with “&” either, since to continue on the rest Matlab code, I will need the output from tool.exe as input to the rest code.

    Could you help me out on this?

    Thanks.

  30. Mike replied on :

    Is there a way to cancel a running system command?

    I’m using ‘dos’ to run a windows batch file and I want some way to terminate the running of dos program from inside MATLAB.

  31. Mike replied on :

    @Mike,
    Did you try Ctrl+C ?

    @Jim,
    I don’t have an easy answer. A lot of it depends on various threading issues involved. Is the DOS program interactive, or does it just need to run to generate output? If it’s the later, maybe you can pipe the output to a file and display that in MATLAB.

  32. Nelson Brown replied on :

    The console application I was trying to run always prompted for input, and it wasn’t obvious to me how to insert that input while running my Matlab script.

    I found a way to do it, which might be useful to you, Person of the Future:

    userinput = ‘yes’;
    output = evalc(sprintf(‘!echo %s | command_that_asks_areyousure’, userinput));

  33. craq replied on :

    Do you know why the system() command would give a different result to a shell? For example, try running system(‘echo random_text > random_file.txt’) twice. I put this on the mathworks newsreader too: http://www.mathworks.com/matlabcentral/newsreader/view_thread/318203

  34. Michael Katz replied on :

    The extra information you provided in the cssm post would have been helpful here too. See the UNIX documentation http://www.mathworks.com/help/techdoc/ref/unix.html on how MATLAB chooses which shell to run in.

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


MathWorks
Mike works on the MATLAB Desktop team.

These postings are the author's and don't necessarily represent the opinions of The MathWorks.