````md # Running MATLAB and GNU Octave Scripts from Bash This document shows common ways to execute MATLAB-style `.m` scripts from a Bash environment using both MATLAB (MathWorks) and GNU Octave. It covers interactive use, non-interactive batch runs, passing arguments, capturing output, and practical patterns for automation and CI. ## Contents - Requirements - Quick comparisons - Running MATLAB scripts from Bash - Interactive mode - Run a script non-interactively - Run a function with arguments - Run one-liners - Working directory and path handling - Capturing output and exit codes - Common MATLAB flags for scripting - Running Octave scripts from Bash - Interactive mode - Run a script non-interactively - Run a function with arguments - Run one-liners - Making `.m` files executable (shebang) - Working directory and path handling - Capturing output and exit codes - Common Octave flags for scripting - Cross-compatibility tips (MATLAB + Octave) - Example: a portable runner script - Troubleshooting ## Requirements ### MATLAB - MATLAB must be installed. - The `matlab` executable must be on your PATH, or you must reference it by full path. - A valid license is required to run MATLAB. Check: ```bash matlab -help | head ```` ### GNU Octave * Octave must be installed. * The `octave` executable must be on your PATH. Check: ```bash octave --version ``` ## Quick comparison | Task | MATLAB | Octave | | ----------------------------- | --------------------------------- | ------------------------ | | Interactive shell | `matlab` (GUI by default) | `octave` | | Headless run (CI) | `matlab -batch "cmd"` (preferred) | `octave --eval "cmd"` | | Run script file | `matlab -batch "run('file.m')"` | `octave --no-gui file.m` | | Exit with code | `exit(n)` | `exit(n)` | | Make `.m` directly executable | uncommon | common via shebang | ## Running MATLAB scripts from Bash ### 1) Interactive mode Starts MATLAB. Depending on your platform and install, this may launch a GUI. ```bash matlab ``` For terminal-only use, prefer `-nodesktop` and optionally `-nosplash`: ```bash matlab -nodesktop -nosplash ``` ### 2) Run a script non-interactively Recommended modern approach: `-batch`. It runs the command and exits when finished. Run a script with `run()`: ```bash matlab -batch "run('myscript.m')" ``` If the script relies on being run from its directory, set the working directory first: ```bash matlab -batch "cd('/path/to/project'); run('myscript.m')" ``` Alternative older pattern: `-r` (less robust for automation because you must ensure MATLAB exits): ```bash matlab -nodisplay -nosplash -r "run('myscript.m'); exit" ``` ### 3) Run a function with arguments If your file defines a function, call it directly. Prefer `-batch`: ```bash matlab -batch "myfunc(123, 'abc')" ``` To pass values from Bash variables: ```bash matlab -batch "myfunc(${N}, '${NAME}')" ``` If arguments may contain quotes or spaces, consider writing a small MATLAB wrapper function that reads environment variables. ### 4) Run one-liners ```bash matlab -batch "disp(2+2)" ``` Multiple statements: ```bash matlab -batch "a=1; b=2; fprintf('%d\n', a+b)" ``` ### 5) Working directory and path handling Common options: * Change directory at startup: ```bash matlab -batch "cd('/path/to/project'); myfunc()" ``` * Add code directories to MATLAB path: ```bash matlab -batch "addpath('/path/to/lib'); myfunc()" ``` To include subfolders: ```bash matlab -batch "addpath(genpath('/path/to/project')); myfunc()" ``` ### 6) Capturing output and exit codes Capture stdout/stderr: ```bash matlab -batch "run('myscript.m')" > matlab.out 2>&1 ``` Check exit code: ```bash matlab -batch "run('myscript.m')" echo $? ``` To explicitly fail a pipeline, use `exit(1)` on error. Example pattern: ```matlab try run('myscript.m'); catch ME disp(getReport(ME)); exit(1); end exit(0); ``` Run it: ```bash matlab -batch "try, run('myscript.m'); catch ME, disp(getReport(ME)); exit(1); end; exit(0);" ``` ### 7) Common MATLAB flags for scripting Commonly useful options: * `-batch "cmd"`: run command, return a process exit code, then exit * `-nodisplay`: no display (useful on headless systems) * `-nodesktop`: no desktop GUI * `-nosplash`: no startup splash * `-r "cmd"`: run command; must include `exit` if you want it to terminate Exact availability varies by MATLAB release, so use `matlab -help` for your version. ## Running GNU Octave scripts from Bash ### 1) Interactive mode ```bash octave ``` Quieter: ```bash octave --quiet ``` ### 2) Run a script non-interactively Run a file and exit: ```bash octave --no-gui myscript.m ``` Quieter: ```bash octave --quiet --no-gui myscript.m ``` Some environments use: ```bash octave --no-window-system myscript.m ``` ### 3) Run a function with arguments If `myfunc.m` defines a function `myfunc`, call it via `--eval`: ```bash octave --quiet --eval "myfunc(123, 'abc')" ``` If your function is not on the Octave path, add paths first: ```bash octave --quiet --eval "addpath('/path/to/project'); myfunc()" ``` ### 4) Run one-liners ```bash octave --quiet --eval "disp(2+2)" ``` Multiple statements: ```bash octave --quiet --eval "a=1; b=2; printf('%d\n', a+b);" ``` ### 5) Making `.m` files executable (shebang) This is a common "standalone script" pattern in Octave. Create `myscript.m`: ```matlab #!/usr/bin/env octave disp("Hello from Octave"); ``` Make executable: ```bash chmod +x myscript.m ``` Run: ```bash ./myscript.m ``` If you need flags (quiet, no GUI), use a wrapper script instead, because the shebang line typically supports limited arguments across platforms. ### 6) Working directory and path handling Change directory from the shell before running: ```bash cd /path/to/project octave --quiet --no-gui myscript.m ``` Or change directory within Octave: ```bash octave --quiet --eval "cd('/path/to/project'); run('myscript.m');" ``` Add paths: ```bash octave --quiet --eval "addpath('/path/to/lib'); run('myscript.m');" ``` ### 7) Capturing output and exit codes Capture stdout/stderr: ```bash octave --quiet --no-gui myscript.m > octave.out 2>&1 ``` Exit code: ```bash octave --quiet --no-gui myscript.m echo $? ``` To force non-zero exit on error, wrap execution: ```matlab try run('myscript.m'); catch err disp(err.message); exit(1); end exit(0); ``` Run it: ```bash octave --quiet --eval "try, run('myscript.m'); catch err, disp(err.message); exit(1); end; exit(0);" ``` ### 8) Common Octave flags for scripting Useful options: * `--eval "cmd"`: run a command string * `--quiet`: suppress startup messages * `--no-gui`: disable GUI * `--no-window-system`: similar headless mode on some installs * `--persist`: keep Octave open after running commands (opposite of batch behavior) Check: ```bash octave --help | head -n 50 ``` ## Cross-compatibility tips (MATLAB and Octave) 1. Prefer functions over scripts for automation Functions give cleaner parameter passing and namespace handling. 2. Avoid toolbox-specific calls if you need portability Many MATLAB toolboxes have no Octave equivalent. 3. Be careful with strings and quoting MATLAB and Octave both support `'single quotes'`, and newer MATLAB supports `"double quotes"` strings. For maximum compatibility, prefer single quotes unless you know your Octave version supports double quotes the way you need. 4. Use `fprintf` or `disp` for output For CI logs, keep output simple and deterministic. 5. Ensure exit codes reflect success or failure In both environments, `exit(0)` indicates success, `exit(1)` indicates failure. ## Example: a portable Bash runner This script tries MATLAB first if available, otherwise Octave. Create `run_mfile.sh`: ```bash #!/usr/bin/env bash set -euo pipefail FILE="${1:?Usage: run_mfile.sh path/to/script_or_function.m}" CMD="${2:-}" # optional command override if command -v matlab >/dev/null 2>&1; then if [[ -n "$CMD" ]]; then matlab -batch "$CMD" else matlab -batch "run('${FILE}')" fi elif command -v octave >/dev/null 2>&1; then if [[ -n "$CMD" ]]; then octave --quiet --no-gui --eval "$CMD" else octave --quiet --no-gui "$FILE" fi else echo "Neither matlab nor octave found on PATH" >&2 exit 127 fi ``` Make executable: ```bash chmod +x run_mfile.sh ``` Run: ```bash ./run_mfile.sh myscript.m ``` Or run a function call: ```bash ./run_mfile.sh myfunc.m "myfunc(1, 'abc')" ``` ## Troubleshooting ### MATLAB: command not found * Add MATLAB to PATH, or invoke it by full path, for example: ```bash /Applications/MATLAB_R202x?.app/bin/matlab -batch "disp('ok')" ``` ### Octave: GUI issues on servers * Use `--no-gui` or `--no-window-system`. ### Scripts depend on relative paths * `cd` into the script directory before launching, or do `cd()` within MATLAB/Octave before calling `run()`. ### Quoting problems when passing strings * Avoid complex quoting in `--eval` or `-batch`. * Use environment variables and read them inside MATLAB/Octave when inputs are complicated. ### Different behavior between MATLAB and Octave * Check for unsupported functions or toolbox calls. * Run minimal repro steps using `--eval` or `-batch` to isolate incompatibilities.