# Std::process on windows is escaping raw literals which causes problems with chaining commands

**URL:** <https://internals.rust-lang.org/t/std-process-on-windows-is-escaping-raw-literals-which-causes-problems-with-chaining-commands/8163>\
**Category:** Uncategorized\
**Created:** [August 8, 2018, 11:24pm UTC](https://internals.rust-lang.org/t/std-process-on-windows-is-escaping-raw-literals-which-causes-problems-with-chaining-commands/8163 "2018-08-08T23:24:57Z")\
**Posts on this page:** 1\
**Showing post:** 7

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [August 9, 2018, 1:04am UTC](https://internals.rust-lang.org/t/std-process-on-windows-is-escaping-raw-literals-which-causes-problems-with-chaining-commands/8163/7 "2018-08-09T01:04:48Z")

</div>

This is implemented:

> **[Command in std::process - Rust](https://doc.rust-lang.org/stable/std/process/struct.Command.html#method.raw_arg)**
>
> A process builder, providing fine-grained control over how a new process should be spawned.

* * *

Given how messy the syntax of some legacy Windows commands can be, it may be useful to extend `Command` to support arbitrary syntax.

I think the simplest would be to add a method such as:

```rust
fn arguments_escaped(&mut self, the_command_line: &str) -> &mut Self

```

that takes the whole command line except the command name itself. So:

```rust
Command::new("foo").arguments_escaped("\\ args \" bar \" \"\"\" baz")

```

would execute command + space + `arguments_escaped` value verbatim, so `GetCommandLineW` in the executed command would be:

```
foo \ args " bar " """ baz

```

I've named it `_escaped`, meaning _already escaped_, because the caller is responsible for escaping arguments using some command-specific syntax (the name could be `raw_args` or anything else 🚲). The syntax is arbitrary as interpreted by the command being executed, so the Rust stdlib can't possibly know the syntax for all commands. User of `Command` would have to take that responsibility.

It's not exactly as bad as the Unix equivalent of passing a whole shell command as a string, because by default there's no dangerous shell syntax interpreted. It could be made dangerous if used as `Command::new("cmd").arguments_escaped(format!("/c command {}", args))`, but then it's equivalent of `Command::new("bash").arg("-c").arg(format!("command {}", args))`, which is a bad idea as well.

Linux, and probably other platforms, don't even have a concept of passing raw unparsed command string from the shell, so this method couldn't be portable. It could be OK if it was an extension trait in Windows-specific corner of the stdlib.

## Alternatives:

- Add `.raw_arg(str)`/`.escaped_arg(str)` that just appends a string to the command line (perhaps delimited by spaces). The upside is that it looks more like regular usage of `Command`, but the downside is that `.raw_arg(one).raw_arg(two)` could set expectation of passing two arguments, but the actual meaning of it is impossible to define.

- Add `.arg_with_syntax(str, ArgSyntax::DoesNotSupportNestedQuotes)`, `.arg_with_syntax(str, ArgSyntax::ThisIsTheLastArgAndEverythingFromHereIsVerbatim)` with quoting/sanitisation/mangling options for variously broken ad-hoc parsers.

- Recognize the command being executed (e.g. `dir`, `notepad`, `cmd /c`, `echo`), and choose a different argument serialization syntax appropriate for whatever ad-hoc argument parser that command uses. The upside is that `.arg()` would magically work as intended, the downside is endless whack-a-mole with unlimited set of broken parsers. Also recognizing commands is unreliable (e.g. if the executable gets renamed).

---

_[View the full topic](https://internals.rust-lang.org/t/std-process-on-windows-is-escaping-raw-literals-which-causes-problems-with-chaining-commands/8163)._
