Godot version:
3.2.1
OS/device including version:
macos
Issue description:
OS.execute("/bin/bash", ['-c',"export PATH=test && echo $PATH"], true, output,true)
print(output)
print result
[/usr/bin:/bin:/usr/sbin:/sbin
]
don't work
Steps to reproduce:
Minimal reproduction project:
It also doesn't work in Bash...
$ /bin/bash -c "export PATH=test && echo $PATH"
/home/akien/Projects/godot/emscripten/emsdk:/home/akien/Projects/godot/emscripten/emsdk/upstream/emscripten:/home/akien/Projects/godot/emscripten/emsdk/node/12.9.1_64bit/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/lib64/qt5/bin:/usr/lib64/qt4/bin:/home/akien/.cargo/bin:/home/akien/.local/bin:/home/akien/bin:/home/akien/.cargo/bin
Actually it works when using single quotes to prevent shell expansion:
$ /bin/bash -c 'export PATH=test; echo $PATH'
test
The problem is that we use double quotes to enclose arguments passed to the executable (here /bin/bash), which means that shell variables get expanded. That's likely what most users would expect, but in this case it makes things tricky.
You can work it around by closing the double-quoted string and concatenating with a single-quote enclosed string:
OS.execute("/bin/bash", ['-c', "\"'export PATH=test && echo $PATH'\""], true, output, true)
I'm not sure what we can do to improve this. One solution would be to switch to using single quotes by default (no shell expansion), and then add a boolean parameter to toggle shell expansion (thus using double quotes as delimiter instead of single quotes).
/bin/bash -c 'export PATH=test; echo $PATH'
gdscript don't work
OS.execute("/bin/bash", ['-c','export PATH=test && echo $PATH'], true, output,true)
[/usr/bin:/bin:/usr/sbin:/sbin
]
The problem is that we use double quotes to enclose arguments passed to the executable (here
/bin/bash), which means that shell variables get expanded. That's likely what most users would expect, but in this case it makes things tricky.You can work it around by closing the double-quoted string and concatenating with a single-quote enclosed string:
OS.execute("/bin/bash", ['-c', "\"'export PATH=test && echo $PATH'\""], true, output, true)I'm not sure what we can do to improve this. One solution would be to switch to using single quotes by default (no shell expansion), and then add a boolean parameter to toggle shell expansion (thus using double quotes as delimiter instead of single quotes).
OS.execute("/bin/bash", ['-c', "\"'export PATH=test && echo $PATH'\""], true, output, true)
That's right.
I'll keep it open for now as we might want to change the method, or at least improve the documentation to mention this caveat.
So @bleeptrack and I just stumbled over this problem – we definitely had expected that OS.execute would pass the arguments to the command literally, without any modification. A more stable implementation (using C's execv?) would sure be nice!
@akien-mga, your workaround was helpful and worked, thanks! To preserve single quotes inside the command, we ended up replacing all of them by '"'"', like this:
var command = "echo \"hello 'world'\""
command = '"\''+command.replace("'", "'\"'\"'")+'\'"'
OS.execute("/bin/bash, ["-c", command])
Most helpful comment
I'll keep it open for now as we might want to change the method, or at least improve the documentation to mention this caveat.