Como faço para lidar com caracteres citação ao usar cmd.exe

Estou tentando fazer isso:

cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out" 

No entanto, eu tenho problemas que estão para baixo para o caminho cmd.exe funciona. Se você ler a ajuda para isso, ele manipula “caracteres de uma maneira especial. Veja a ajuda no final da pergunta. Então, isso não é executado corretamente … Eu estou supondo cmd.exe retira algumas citações que fazem o declaração mal formada.

Eu posso fazer isso com sucesso:

 // quotes not required around folder with no spaces cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > C:\temp\FolderWithNoSpaces\SomeProgram.out 

Mas eu realmente preciso que o primeiro funcione. Existe alguma coisa estranha no processamento de citações que o cmd.exe usa? Eu quero preservar todas as citações, mas parece não haver uma opção para fazer isso.


Ajuda tirada da saída de: cmd /?

Se / C ou / K for especificado, o restante da linha de comando após o comutador será processado como linha de comando, onde a lógica a seguir será usada para processar caracteres quote (“):

 1. If all of the following conditions are met, then quote characters on the command line are preserved: - no /S switch - exactly two quote characters - no special characters between the two quote characters, where special is one of: &()@^| - there are one or more whitespace characters between the the two quote characters - the string between the two quote characters is the name of an executable file. 2. Otherwise, old behavior is to see if the first character is a quote character and if so, strip the leading character and remove the last quote character on the command line, preserving any text after the last quote character. 

Ah doh. Acho que respondi minha própria pergunta.

Se você usa / S e quebra a coisa toda entre aspas, apenas remove as aspas externas.

 cmd.exe /S /C " do what you like here, quotes within the outermost quotes will be preserved " 

Acho que você descobrirá que seu exemplo funciona absolutamente bem.

 cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out" 

Eu reproduzi seu exemplo aqui http://pastebin.com/raw.php?i=YtwQXTGN

 C:\>cmd /c "c:\Program Files\my folder\my long program.exe" > "c:\temp\spaces are here\aa" C:\>type "c:\temp\spaces are here\aa" my long program.exe has run C:\> further example demonstrating it works with "my long program.exe", removing cmd /c, it operates fine too. C:\>"c:\Program Files\my folder\my long program.exe" > "c:\temp\spaces are here\ aa" C:\>type "c:\temp\spaces are here\aa" my long program.exe has run C:\> Another example, but with replace. replace with no parameters says "source path required" "no files replaced" C:\>replace > aa Source path required C:\>type aa No files replaced Exactly the same effect when they're in folders with spaces. C:\>cmd /c "c:\Program Files\my folder\replace.exe" > "c:\temp\spaces are here\rr" Source path required C:\>type "c:\temp\spaces are here\rr" No files replaced C:\> further demonstration with replace without cmd /c works fine too. C:\>"c:\Program Files\my folder\replace.exe" > "c:\temp\spaces are here\rr" Source path required C:\>type "c:\temp\spaces are here\rr" No files replaced C:\> 

A razão pela qual seu exemplo funciona bem

 cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out" 

e como / porque funciona da maneira que faz, é porque o> é interpretado como especial pelo host.exe Então, esta parte cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" – Eu acho – é avaliado primeiro. ou seja, cmd / c não vê o> e depois.

cmd /? mostra 2 casos

Caso 1 e Caso 2. Seu exemplo se encheckbox no Caso 1

 If /C or /K is specified, then the remainder of the command line after the switch is processed as a command line, where the following logic is used to process quote (") characters: 1. If all of the following conditions are met, then quote characters on the command line are preserved: - no /S switch - exactly two quote characters - no special characters between the two quote characters, where special is one of: &<>()@^| - there are one or more whitespace characters between the two quote characters - the string between the two quote characters is the name of an executable file. 2. Otherwise, old behavior is to see if the first character is a quote character and if so, strip the leading character and remove the last quote character on the command line, preserving any text after the last quote character. 

Você pode testar com certeza se o seu exemplo se encheckbox no caso 1, porque se você adicionar / s (sem adicionar mais citações ou fazer qualquer alteração no seu exemplo além de adicionar / s), obterá um resultado diferente, porque ele faz Seu caso de sucesso de exemplo 2. Então isso prova que seu exemplo é definitivamente um caso 1. E ele claramente atende a todos os critérios do caso 1. Se o seu exemplo fosse um caso 2, e você adicionasse / s, então não faria diferença .

Sua resposta é interessante porque mostra uma maneira alternativa de obter seu resultado, mas no caso 2. Adicionando citações externas adicionais e adicionando / s.

Mas, na verdade, quando você adiciona essas citações externas adicionais, você acaba de criar um caso 2 e adicionar um / s além disso não fará diferença.

 C:\>cmd /c "c:\Program Files\my folder\replace.exe" Source path required No files replaced C:\>cmd /s /c "c:\Program Files\my folder\replace.exe" 'c:\Program' is not recognized as an internal or external command, operable program or batch file. C:\>cmd /c ""c:\Program Files\my folder\replace.exe"" Source path required No files replaced C:\>cmd /s /c ""c:\Program Files\my folder\replace.exe"" Source path required No files replaced C:\> 

O exemplo na sua pergunta funcionou bem

 cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out" 

Sua alternativa (com as aspas / S e as citações externas) que você dá como resposta para fazer o exemplo funcionar também funciona bem

 cmd.exe /S /C ""C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out"" 

Embora sua resposta, que é uma alternativa, possa realmente ser simplificada removendo-se o / S, porque já é um caso 2, portanto, adicionar / s não fará diferença. Então isso melhoraria a solução dada na sua resposta

 cmd.exe /C ""C:\Program Files\Somewhere\SomeProgram.exe" > "C:\temp\Folder Containing Spaces\SomeProgram.out"" 

Seu exemplo, que você descreveu como um problema em sua pergunta e sua solução, produz o mesmo resultado positivo. Mas uma grande diferença, suponho, (e não sei como testar isso), mas uma diferença na forma como o seu exemplo funciona e como funciona a solução da sua resposta é, no caso do seu exemplo, o cmd.exe de hospedagem / invocação faz o redirecionamento para o arquivo. Enquanto no exemplo da sua solução, o cmd.exe chamado é passado pelo cmd.exe do host e, portanto, o cmd.exe chamado faz o redirecionamento. Também é claro, seu exemplo é um caso 1, enquanto sua solução é uma emenda que você fez (muito bem) para que funcione no caso 2.

Espero não ter errado aqui, posso ter. Mas sua pergunta e resposta me ajudaram a entender como o cmd e, em particular, o cmd / c está funcionando!

Talvez o seu exemplo tenha sido uma simplificação excessiva do seu atual, e o seu atual fracassou e precisou da sua emenda. Se o seu caso de exemplo tivesse sido um pouco mais complexo, por exemplo, ter um parâmetro para o programa que usou aspas, ele falharia no Caso 1 e você precisaria de cotações de saída (/ S não alteraria o resultado , então não / S seria necessário, como já seria um caso 2, uma vez que você adicionar as citações externas necessárias). Mas o exemplo que você deu na sua pergunta parece-me funcionar bem.

Adicionado – Um Q e um relacionados O que é `cmd / s` para?