Unity, Process.Start(), bin/bash...and quotes

Hello to everyone,

I’m going completely crazy with this problem ! :wink:

I’m trying to launch RetroArch with path parameters…which can obviously include spaces.

Launched by ‘Terminal’ this line runs correctly:

"/Applications/RetroArch.app/Contents/MacOS/RetroArch" -L mame2010_libretro.dylib "/Users/imac/Documents/Emulation/MAME/**Roms OK**/88games.zip"

Once in Unity, this code also works:

ProcessStartInfo startInfo = new ProcessStartInfo()
{
    FileName = "/bin/bash",
    UseShellExecute = false,
    Arguments = "-c \"" + "/Applications/RetroArch.app/Contents/MacOS/RetroArch" + " -L mame2010_libretro.dylib " + "/Users/imac/Documents/Emulation/MAME/Roms/88games.zip" + "\""
};

Process myProcess = new Process
{
    StartInfo = startInfo
};

myProcess.Start();
myProcess.WaitForExit();

…but that’s because there is not a single space in any of the paths or filenames! As soon as there is a space, nothing to do it doesn’t work! I can add quotes and escape them or double or triple quotes…nothing works!

Let’s take for instance the last path: "/Users/imac/Documents/Emulation/MAME/Roms/88games.zip" and imagine there is a space in it like so: “/Users/imac/Documents/Emulation/MAME/Roms OK/88games.zip”. I surround it by escaped quotes: "\"/Users/imac/Documents/Emulation/MAME/Roms OK/88games.zip\""…but it will never succeed!

What is please my error? It’s like obviously the quoted path is never ‘seen’ by bin/bash!

Thanks a lot for any help!

which cores have you tested this behavior with? That is, it’s more likely to be an issue with the path on the core’s end than on RetroArch’s end (and probably easier to fix, too).

…perhaps, but would it work nicely once launched by ‘Terminal’ then? I’m testing on mame2010_libretro.dylib and stella_libretro.dylib

hmm yeah, true. So the issue is Unity isn’t passing the command properly escaped, regardless of you escaping it?

The string that is sent as argument to bash is correctly formatted (so with the quotes well present), I can debug this…but it’s like they are not interpreted as such by bash!?

Hmm, yeah, bash can be weird about that. Would it help if you put a backslash in front of the quotes? Or instead of passing the path directly right there, feed it to bash as “$@” and then define the path elsewhere in Unity, so it just passes the string as if it were typed in by a user?

Thank you very much for the reply! It seems promising…but I’ll have to investigate and sort this out cause I’m totally new to Mac development (I’m porting an app from Windows to Mac) and all this bash/$@ stuff is enigmatic for me :wink: Would you by chance have time to give me a little example of how feeding a “$@” to bash (referencing a variable I guess?) work?

Unfortunately, I know nothing of Unity nor Mac development, and only enough bash to be dangerous. This Quora answer does a better job than I could on the advantages of using “$@”: https://www.quora.com/What-does-“-”-mean-in-Bash

And yeah, just referencing a variable is what I meant.

1 Like

hunterk, thanks for your help!

Thanks to the direction you gave me I was able to get it done!

Boy, did it take me hours of trial and error!

So it’s your direction and then these posts

https://unix.stackexchange.com/a/144519, https://stackoverflow.com/a/26167919

…and these key phrases that helped me:

You are using double-quotes, so the parent shell is interpolating backticks and variables before passing the argument to /bin/bash

Extra arguments are assigned as positional parameters to the shell process that’s launched, not passed as arguments to the command

So, here is the theory

/bin/bash -c 'echo "$0" "$1"' foo bar

…and put into practice (sorry, here for Mame, not RetroArch)

ProcessStartInfo startInfo = new ProcessStartInfo()
{
    FileName = "/bin/bash",
    UseShellExecute = false,
    CreateNoWindow = false,
    WorkingDirectory = "/Applications/RetroArch.app/Contents/MacOS/",
    Arguments = "-c '/Users/imac/Downloads/MAME_for_MacOSX_0.212-64bit/mame64 \"$0\" \"$1\" \"$2\"' \"-rompath\" \"/Users/imac/Documents/Emulation/MAME/Roms OK\" \"88games.zip\""
};
Process myProcess = new Process
{
    StartInfo = startInfo
};
myProcess.Start();
myProcess.WaitForExit();

The solution was therefore the joint use of single quotes, substitution variables and escaped double quotes :wink:

1 Like

awesome! I’m glad you got it going :slight_smile: