Как мне работать с символами кавычек при использовании cmd.exe

Я пытаюсь сделать это:

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

Однако у меня есть проблемы, связанные с тем, как работает cmd.exe. Если вы прочитали справку для него, он обрабатывает символы "особым образом. См. Справку в конце вопроса. Итак, это не выполняется правильно ... Я предполагаю, что cmd.exe отбрасывает некоторые кавычки, что делает Заявление плохо сформировано.

Я могу сделать это успешно:

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

Но мне действительно нужен первый, чтобы работать. Есть ли где-нибудь странная обработка цитат, которую использует cmd.exe? Я хочу, чтобы он сохранил все кавычки, но, похоже, нет возможности сделать это.


Помощь взята из вывода: cmd /?

Если указано / C или / K, то оставшаяся часть командной строки после переключателя обрабатывается как командная строка, где для обработки символов кавычек (") используется следующая логика:

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.
10.12.2008 13:10:23
Когда я пробую эквивалентный пример, он работает без / S. Я скопировал c: \ windows \ system32 \ replace.exe в c: \ и переименовал копию «rep lace.exe», чтобы в ней было свободное место. замена при выполнении без параметров дает 2 строки, одну для stderr и одну для stdout. так что это хороший пример. C: \> cmd / c "rep lace"> "aa a" <---, который работал так же, как и без cmd / c. Меня интересует, как cmd разбирает вещи, есть ли у вас идеи, почему расхождение между вашим примером и моим примером? или как я могу воссоздать твой пример? та
barlop 11.12.2012 19:27:03
@ barlop - Пожалуйста, постарайся усерднее в первую очередь. Почему бы вам не попробовать сделать ваш пример более похожим на мой? Вставьте замену в папку с файлами программы, введите «.exe» в конце имени и выведите в файл, который находится в папке с пробелами. Посмотрите, что происходит потом.
Scott Langham 12.12.2012 10:24:22
здесь pastebin.com/raw.php?i=YtwQXTGN отлично работает для случая, который вы дали
barlop 18.12.2012 03:53:46
2 ОТВЕТА
РЕШЕНИЕ

Ах. DOH. Думаю, я ответил на свой вопрос.

Если вы используете / S и заключаете все это в кавычки, это просто удаляет эти внешние кавычки.

cmd.exe /S /C " do what you like here, quotes within the outermost quotes will be preserved "
76
16.06.2016 15:29:05
Таким образом, с помощью ключа / S вы заключаете все пути к файлам / исполняемым файлам в кавычки, а затем всю команду в другой набор кавычек. Работал на меня, спасибо!
Simon East 5.07.2011 03:36:33
О Боже. cmd /? помощь стоит меньше, чем ничего. Это на самом деле запутало этот очень простой ответ.
David Chappelle 27.03.2012 02:20:35
Мне любопытно увидеть пример, где цитаты съедены. Если я сделаю cmd / c echo "abc" msg "def", кавычки сохранятся. И если я сделаю это с / с. cmd / s / c "abc" msg "def" кавычки все еще сохраняются.
barlop 11.12.2012 23:59:42

Я думаю, вы обнаружите, что ваш пример работает абсолютно нормально.

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

Я воспроизвел ваш пример здесь http://pastebin.com/raw.php?i=YtwQXTGN

C:\>cmd /c "c:\Program Files\my folder\my long program.exe" > "c:\temp\spaces are here\a.a"

C:\>type "c:\temp\spaces are here\a.a"
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\
a.a"

C:\>type "c:\temp\spaces are here\a.a"
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 > a.a
Source path required

C:\>type a.a
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\r.r"
Source path required

C:\>type "c:\temp\spaces are here\r.r"
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\r.r"
Source path required

C:\>type "c:\temp\spaces are here\r.r"
No files replaced

C:\>

Причина, по которой ваш пример работает нормально

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

и как / почему это работает так, как это происходит, потому что>> интерпретируется как специальный файл host.exe. Так что эта часть cmd.exe /C "C:\Program Files\Somewhere\SomeProgram.exe"- я думаю - оценивается первой. т.е. cmd / c не видит> и после.

cmd /? показывает 2 случая

Случай 1 и Случай 2. Ваш пример подходит для случая 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.

Вы можете проверить, что ваш пример соответствует случаю 1, потому что, если вы добавите / s (без добавления дополнительных кавычек или внесения каких-либо изменений в ваш пример, кроме добавления / s), то вы получите другой результат, потому что он делает ваш пример попал в случай 2. Таким образом, это доказывает, что ваш пример определенно является случаем 1. И он явно соответствует всем критериям случая 1. Если бы ваш пример был случаем 2, а вы добавили / s, то это не имеет значения ,

Ваш ответ интересен, потому что он показывает альтернативный способ получения вашего результата, но в случае 2. Добавляя дополнительные внешние цитаты и добавляя / s.

Но на самом деле, когда вы добавляете эти дополнительные внешние кавычки, вы просто включили вариант 2, и добавление / s поверх этого не будет иметь значения.

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:\>

Пример в вашем вопросе работал нормально

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

Ваш вариант (с / S и внешними кавычками), который вы даете в качестве ответа, чтобы пример работал, тоже работает хорошо

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

Хотя ваш ответ, который является альтернативой, на самом деле можно упростить, удалив / S, потому что это уже случай 2, поэтому добавление / s не будет иметь никакого значения. Так что это улучшит решение, данное в вашем ответе

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

Ваш пример, который вы назвали проблемой в своем вопросе, и ваше решение, дают одинаково хороший результат. Но я полагаю, что есть одно большое различие (и я не уверен, как это проверить), но одно отличие в том, как работает ваш пример и как работает решение в вашем ответе, - я думаю, что в случае вашего примера, cmd.exe хостинга / вызова выполняет перенаправление в файл. В то время как в примере вашего решения вызываемый cmd.exe передается> узлом cmd.exe, и поэтому вызываемый cmd.exe выполняет перенаправление. Также, конечно, ваш пример - это случай 1, а ваше решение - это поправка, которую вы внесли (очень хорошо), чтобы она работала в случае 2.

Я надеюсь, что я не ошибся здесь, возможно, у меня есть. Но ваш вопрос и ответ помогли мне понять, как работает cmd и, в частности, cmd / c!

Возможно, ваш пример был упрощением вашего фактического, а ваш действительный потерпел неудачу и нуждался в вашей поправке. Если ваш пример был немного более сложным, например, с параметром для программы, которая принимает кавычки, то он потерпел бы неудачу в случае 1, и вам действительно потребуются внешние кавычки (/ S не изменит результат , поэтому нет необходимости в / S, так как это уже будет случай 2, когда вы добавите необходимые внешние кавычки). Но пример, который вы привели в своем вопросе, на самом деле мне кажется, работает нормально.

Добавлено - связанные вопросы и ответы. Зачем нужен cmd / s?

9
23.05.2017 12:26:14
Очень подробное расследование. Вы можете быть правы, я действительно упростил вопрос через некоторое значительное время после публикации. Я видел, что этот вопрос часто просматривался, поэтому подумал, что постараюсь удалить ненужные детали ... но, возможно, они были актуальны. Пожалуйста, посмотрите на историю вопроса, чтобы увидеть оригинал.
Scott Langham 19.12.2012 09:53:27
@ScottLangham, похоже, в оригинале также было упрощение с «someprogram» и «папка с пробелами» и без параметра «someprogram». Ровно 2 кавычки перед перенаправлением. Я думаю, что если ваша «какая-то программа» имеет параметр с кавычками, а затем перенаправляется, то она попадет в Случай 2, описанный в cmd /?, И потребует внешних кавычек. (хотя все равно не понадобится / S). Но ваш пример, который, кажется, даже в оригинале, для cmd / c "некоторая программа"> ... Это все еще подходит для случая 1 и работает нормально.
barlop 19.12.2012 14:18:49
@ScottLangham Если бы вы случайно добавили третью кавычку перед перенаправлением (что, я думаю, могло произойти в ситуации программирования с экранированными кавычками, как это может показаться сложным), то это также привело бы к случаю 2 (так как было бы больше, чем 2 цитаты), и тогда вам понадобятся внешние цитаты, чтобы заставить его вести себя правильно. (хотя все еще нет / s, так как / s просто для того, чтобы случай 1 перешел к случаю 2, и не меняет поведение того, что уже есть случай 2).
barlop 19.12.2012 14:20:10
@ ScottLangham Я тоже могу ошибаться, потому что это немного сложно. И мы не можем напрямую проверить ваши примеры. Идеальной вещью в этом вашем старом вопросе было бы использование стандартной команды, например replace.exe, где можно просто скопировать / вставить пример и получить результат, о котором вы говорили. И я могу только догадываться, почему ваш реальный пример (перед любым упрощением, а не «какой-то папкой» и т. Д.) Попал бы в случай 2. (Я полагаю, у вас было еще 1 + кавычки перед перенаправлением. Следовательно,> 2 кавычки перед переадресация, следовательно, не соответствует случаю 1 и идет к случаю 2.
barlop 19.12.2012 14:23:02
Это слишком сложно для меня. Если вы сомневаетесь, я говорю, используйте / S и поместите дополнительную пару цитат вокруг ... по крайней мере, вы точно знаете, что вы получаете.
Scott Langham 20.12.2012 09:42:11