2012-03-26 1 views
26

Командная строка Windows (cmd.exe) имеет необязательный /s parameter, который изменяет поведение /c (запустите определенную команду, а затем выйдет) или /k (запустите определенную команду, а затем отобразите приглашение оболочки). Этот параметр /s, очевидно, имеет какое-то отношение к какому-то управлению тайной цитатой.Что такое `cmd/s`?

The docs запутаны, но, насколько я могу сказать, когда вы делаете cmd /csomething, и something содержит кавычки, то по умолчанию cmd иногда сдирать эти цитаты, и /s говорит его оставить они одни.

Что я не понимаю, когда удаление цитаты сломает что-либо, потому что это единственный раз, когда /s («подавить поведение по умолчанию для удаления котировок») будет необходимо. Он удаляет только кавычки под определенным тайным набором условий, и одним из таких условий является то, что первым символом после /c должен быть кавычек. Таким образом, это не удаление котировок вокруг аргументов; это либо удаление кавычек по пути к EXE, в котором вы работаете, либо вокруг всей командной строки (или, возможно, около первой половины командной строки, что было бы странно).

  • Если указан путь к EXE, например. cmd /c "c:\tools\foo.exe" arg1 arg2, тогда цитаты не нужны, и если cmd хочет их удалить, штраф. (Он не удалит их, если у пути есть пробел в имени - это еще один из тайных правил.) Я не могу представить никаких причин для подавления удаления цитат, поэтому /s кажется ненужным.
  • Если указана вся командная строка, например. cmd /c "foo.exe arg1 arg2", то кажется, что удаление цитаты было бы необходимо, поскольку в системе нет EXE с именем foo.exe arg1 arg2; поэтому кажется, что отказ от цитаты с использованием /s фактически нарушит все. (На самом деле, однако, это не нарушает вещи: cmd /s /c "foo.exe arg1 arg2" работает просто отлично.)

Есть несколько тонкостей /s, который меня ускользает? Когда это когда-нибудь понадобится? Когда это даже изменит ситуацию?

+0

Вот кто-то, кто говорит '/ s', помог ему: http://stackoverflow.com/questions/355988/how-do-i-deal-with-quote-characters-when-using-cmd-exe Я не знаю, t точно знает, что делает 'RunProgram()' сделал/делает, но попытка перепрограммировать проблему в командной строке мне некуда. Все, что я знаю, это то, что синтаксический анализ команды cmd.exe (особенно с экранирующими символами) иногда бывает странным, поэтому я не сомневаюсь, что '/ s' полезен хотя бы по одному случаю. –

+0

@MichaelBurr: Я уверен, что ему просто нужна дополнительная пара котировок;/s в этом случае было избыточным, поскольку условия, при которых/s не имеют значения, не выполнялись. Но это не наносит вреда, и это означает, что код будет работать одинаково, независимо от того, как изменилась команда. –

+1

Я считаю это полезным по причинам, указанным @HarryJohnston. Также это вопрос программирования при программировании с использованием сценариев оболочки Windows CMD, поэтому не уверен, почему люди голосуют, закрываясь как «вне темы». – Ben

ответ

10

Вот пример того, как это может измениться.

Предположим, у вас есть два исполняемых файла: c:\Program.exe и c:\Program Files\foo.exe.

Если вы говорите

cmd /c "c:\Program Files\foo" 

вы будете работать foo.exe (без аргументов), тогда как, если вы говорите

cmd /s /c "c:\Program Files\foo" 

вы будете работать Program.exe с Files\foo в качестве аргумента.

(Как ни странно, в первом примере, если foo.exe не существует, Program.exe будет работать вместо этого.)

Добавление:, если бы вы были типа

c:\Program Files\foo 

в командной строке, то будет работать Program.exe (как это происходит с CMD/с/с), а не foo.exe (как это происходит только с cmd/c). Поэтому одной из причин использования/s было бы, если вы хотите убедиться, что команда анализируется точно так же, как если бы она была введена в командной строке. Вероятно, это скорее всего желательно в сценарии в вопросе, связанном с Michael Burr, где cmd.exe запускается CreateProcess, а не из командного файла или самой командной строки.

То есть, если вы говорят

CreateProcess("cmd.exe", "cmd /s /c \"" MY_COMMAND "\"", ...) 

то строка MY_COMMAND будет анализироваться точно так, как если бы это были введены в командной строке. Если вы берете ввод с командной строки от пользователя или если вы работаете с библиотекой, обрабатывающей командную строку, предоставляемую приложением, это, вероятно, хорошая идея. Например, функция C runtime library system() может быть реализована таким образом.

+0

Вы должны повторить название программы как часть второго аргумента createprocess. 'CreateProcess (" cmd.exe "," CMD.exe/s/c \ "" MY_COMMAND "\" ", ...)'. Первый говорит, какой исполняемый файл запускаться, второй - командная строка, но исполняемый файл ожидается как первая часть командной строки по соглашению, и действительно, первый аргумент может быть опущен и будет выведен из второго аргумента (не рекомендуемые). – Ben

+0

@Ben: Да, это рекомендуемая практика, но обратите внимание, что это не обязательно. Я думаю, что мой фрагмент кода будет работать так, как написано. (Тем не менее, любой, кто на самом деле пишет код, должен следовать совету Бена.) –

+0

@Ben Но, как указывает Гарри, я наблюдал за тем же и согласен, вижу мои комментарии и отвечаю на этот вопрос http://stackoverflow.com/ Вопросы/355988/how-do-i-deal-with-quote-characters-when-using-cmd-exe. В этом вопросе/S кажется излишним. Можете ли вы показать пример, где/S полезно и выполняет функцию? Действительно, для cmd.exe/s/c "c: \ program files \ blah.exe .." это бесполезно и выполняет функцию (когда будет указывать путь и не хочет сохранять пробелы?). Но где это полезно и функционал? В случае добавления котировок выходов/S ничего не делает. – barlop

14

Cmd/S очень полезен, так как это избавляет вас от беспокойства о «цитировании цитат». Напомним, что аргумент /C означает «выполнить эту команду, как если бы я набрал ее в подсказке, а затем выйти».

Итак, если у вас есть сложная команда, которую вы хотите передать в CMD.exe, вам либо нужно помнить правила цитирования аргументов CMD, и надлежащим образом избегать всех котировок, либо использовать , что вызывает специальное правило непарагрерования «Стриптиз первый и последний " и обрабатывать все остальные символы как команду для выполнения без изменений».

Вы бы использовали его, чтобы использовать возможности оболочки CMD, а не напрямую обращаться к другой программе. Например, расширение переменной среды, выход или перенаправление ввода или использование встроенных модулей CMD.exe.

Пример:

Использование оболочки встроенный: Это выполняется как если бы вы ввели DEL /Q/S "%TMP%\TestFile" в строке:

CMD.exe /S /C " DEL /Q/S "%TMP%\TestFile" " 

Это выполняет SomeCommand.exe перенаправлять стандартный вывод временный файл и стандартная ошибка в том же месте:

CMD.exe /S /C " "%UserProfile%\SomeCommand.exe" > "%TMP%\TestOutput.txt" 2>&1 " 

Так что же /S даст вам дополнительные? В основном это избавляет вас от необходимости беспокоиться о цитировании цитат. Это также помогает там, где вы не уверены, например, что переменная среды содержит символы кавычек. Просто скажите /S и добавьте дополнительную цитату в начале и конце.

Смутно Связанные: $ * в Bourne Shell.

Некоторые фон

Напомним, что список аргументов для основной() является С-изма и Unix-изма. Оболочка Unix/Linux (например, Bourne Shell и т. Д.) Интерпретирует командную строку, исключает аргументы, расширяет подстановочные знаки, такие как *, в списки файлов и передает список аргументов вызываемой программе.

Так что, если вы говорите:

$ vi *.txt 

Команда VI видит, например, эти аргументы:

vi 
a.txt 
b.txt 
c.txt 
d.txt 

Это потому, что UNIX/Linux работает внутренне на основе "списка аргументов".

Windows, которая в конечном итоге извлекается из CP/M и VAX, не использует эту систему внутренне. В операционной системе командная строка представляет собой всего лишь одну строку символов. Ответственность вызываемой программы заключается в том, что она интерпретирует командную строку, расширяет файловые глобы (* и т. Д.) И обрабатывает нечеткие цитируемые аргументы.

Итак, аргументы, ожидаемые C, должны быть взломаны библиотекой времени выполнения C. Операционная система предоставляет только одну строку с аргументами, и если ваш язык не является C (или даже если он есть), он не может быть интерпретирован как аргументы, разделенные пробелами, указанные в соответствии с правилами оболочки, но как нечто совершенно иное.

+0

До «какого-то фона» я не понимаю, как правильно вы говорите. См. Здесь http://pastebin.com/raw.php?i=t60teCTk Попробуйте cmd/s/c "" c: \ program files \ replace.exe ">" c: \ temp \ my folder \ aa "" теперь удалить/s и он все еще работает. Так в чем смысл/S? – barlop