3
$\begingroup$

In my "Documents" folder I've created two directories with names "тест" and "тест 2". When I try to use RunProcess for obtaining directory listing for the first directory it works as expected:

RunProcess[{"cmd", "/c", "\"dir /b \"D:\\Documents\\тест\"\""}]    
<|"ExitCode" -> 0, "StandardOutput" -> "test file.txt

  ", "StandardError" -> ""|>

But for the second directory it fails telling that the file is not found:

RunProcess[{"cmd", "/c", "\"dir /b \"D:\\Documents\\тест 2\\\"\""}]    
<|"ExitCode" -> 1, "StandardOutput" -> "", 
 "StandardError" -> "Не удается найти указанный файл.

  "|>

It is interesting that the same happens when I remove the additional quotes around the directory path:

RunProcess[{"cmd", "/c", "\"dir /b D:\\Documents\\тест 2\\\""}]    
<|"ExitCode" -> 1, "StandardOutput" -> "", 
 "StandardError" -> "Не удается найти указанный файл.

  "|>

If I remove the ending backslash \\, I get the directory listing for the directory "тест" (instead of "тест 2") and the "File Not Found" error:

RunProcess[{"cmd", "/c", "\"dir /b D:\\Documents\\тест 2\""}]    
<|"ExitCode" -> 1, "StandardOutput" -> "test file.txt

  ", "StandardError" -> "Файл не найден

  "|>

Wrapping the directory path with quotes changes nothing:

RunProcess[{"cmd", "/c", "\"dir /b \"D:\\Documents\\тест 2\"\""}]
<|"ExitCode" -> 1, "StandardOutput" -> "test file.txt

  ", "StandardError" -> "Файл не найден

  "|>

It looks like the quotes are simply ignored...

Why is that? Is it a bug? Is there a workaround?

When I try the old Import route everything works as expected:

Import["!dir /b \"D:\\Documents\\тест 2\\\"", "Text"]
"test file 2.txt"
$\endgroup$
3
  • $\begingroup$ In Mac OS X with Version 12.0 things are working fine space-wise using both "тест" and "тест 2", but the Cyrillic file names are not displayed with the Cyrillic alphabet. $\endgroup$ Commented Aug 25, 2019 at 14:27
  • $\begingroup$ @AntonAntonov I've posted decoded outputs into the question so that they do not look like garbage. $\endgroup$ Commented Aug 25, 2019 at 15:06
  • $\begingroup$ Thanks for the clarification! $\endgroup$ Commented Aug 25, 2019 at 17:52

1 Answer 1

2
$\begingroup$

Update

I developed the following workflow in an attempt make the process a little more robust.

First, I created a directory and test file with no spaces or special character. Then I opened a command shell to confirm that the command is working as expected with simple characters. Once it is working as expected, I saved the command history as shown in the screen cap below.

Dos Command Session

Next, I imported the history as a table in Mathematica

SetDirectory[NotebookDirectory[]];
histtable = Import["hist.txt", "Table"]
(* {{"cd", "Dropbox\\WolframCommunity"}, {"dir", "/b", 
  "e:DocTest\\testdir"}, {"doskey", "/History", ">", "hist.txt"}} *)

I see that the second to the last element of the list contains the DOS command that I want to process. So, I created a function to replace my command list with simple names to arbitrary names.

cmdfunction[dir_] := {"cmd", "/c"}~
  Join~(StringReplace["testdir" -> dir] /@ histtable[[-2]])

Now, we can test if RunProcess works on our troublesome folder.

RunProcess@cmdfunction["тест 2"]
(* <|"ExitCode" -> 0, "StandardOutput" -> "test file 2.txt

  ", "StandardError" -> ""|> *)

It appears to work. Perhaps, this workflow could be adapted to prepare other DOS commands for RunProcess to take out some of the guesswork.

Original

I broke the command up and got it to work on my system (note that I did it in E:\DocTest).

RunProcess[{"cmd", "/c", "dir", "/b", 
  "E:\\DocTest\\тест 2\\"}]
(* <|"ExitCode" -> 0, "StandardOutput" -> "test file 2.txt

  ", "StandardError" -> ""|> *)
$\endgroup$
6
  • $\begingroup$ Thank you, it works. But why the method in the question fails? I simply adapted the code from the Docs example RunProcess[{"cmd", "/c", "\"date /t\""}]. $\endgroup$ Commented Aug 25, 2019 at 13:59
  • $\begingroup$ It seems like RunProcess is pretty complex under the hood. I had to kill TracePrint on your simple command since it produced lots of output. I think the issue is that windows quoting requirements vary depending on whether there are spaces in paths or arguments as shown in the examples section found here. In the date case, there is one spaceless argument. In the dir case, you have two arguments with one that may/may not contain a space. RunProcess seems to apply the proper quoting requirements if the command is broken into individual arguments. $\endgroup$
    – Tim Laska
    Commented Aug 25, 2019 at 15:38
  • $\begingroup$ It looks so. But what I don't understand is how RunProcess could decide whether quoting should be applied or not. May be it just uses some another mechanism of passing arguments to executables? Quoting is nesessary due to ambiguity of interpretation of the input, may be there is another way to pass arguments to functions which doesn't require building a full command line (as we do when typing in the cmd terminal) and allows passing arguments one-by-one without ambiguity? $\endgroup$ Commented Aug 25, 2019 at 16:01
  • $\begingroup$ The "/c", "dir", "/b", and so on are arguments to the command "cmd" as is documented RunProcess[{"command", arg1, arg2,...}]. They can not be combined but must be given separately. $\endgroup$
    – Somos
    Commented Aug 25, 2019 at 18:15
  • $\begingroup$ @Somos I agree with your statement, but @Alexey's date example appears to violate it. Note how RunProcess[{"cmd", "/c", "\"date /t\""}] and RunProcess[{"cmd", "/c", "date", "/t"}] both appear to work and the first example, which appears to combine arguments, was pulled from the docs. $\endgroup$
    – Tim Laska
    Commented Aug 25, 2019 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.