Что такое `cmd/s`?
Командная строка Windows (cmd.exe
) имеет необязательный параметр /s
, который изменяет поведение /c
(запустит определенную команду, а затем выйдет ) или /k
(запустите определенную команду, а затем отобразите приглашение оболочки). Этот параметр /s
, очевидно, имеет какое-то отношение к какому-то управлению тайной кавычкой.
Документы запутывают, но насколько я могу судить, когда вы делаете cmd /c
something
, а 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
, которая ускользает от меня? Когда это когда-нибудь понадобится? Когда это будет даже иметь значение?
Ответы
Ответ 1
Cmd/S очень полезен, так как это избавляет вас от беспокойства о "цитировании цитат". Напомним, что аргумент /C
означает "выполнить эту команду, как если бы я набрал ее в приглашении, а затем выйти".
Итак, если у вас есть сложная команда, которую вы хотите передать в CMD.exe, вам либо нужно помнить правила цитирования аргументов CMD, и надлежащим образом избегать всех котировок, либо использовать /S
, который запускает специальный не-парсинг правило "Снять первый и последний "
и обрабатывать все остальные символы как команду для выполнения без изменений".
Вы бы использовали его там, где хотите использовать возможности оболочки CMD, а не напрямую обращаться к другой программе. Например, расширение переменной среды, выход или перенаправление ввода или использование встроенных модулей CMD.exe.
Пример:
Использовать встроенную оболочку: это выполняется, если вы набрали DEL /Q/S "%TMP%\TestFile"
в командной строке:
CMD.exe /S /C " DEL /Q/S "%TMP%\TestFile" "
Это выполняет SomeCommand.exe перенаправление стандартного вывода в файл temp и стандартную ошибку на одно и то же место:
CMD.exe /S /C " "%UserProfile%\SomeCommand.exe" > "%TMP%\TestOutput.txt" 2>&1 "
Итак, что дает /S
вам дополнительное? В основном это избавляет вас от необходимости беспокоиться о цитировании цитат. Это также помогает там, где вы не уверены, например, что переменная среды содержит символы кавычек. Просто скажите /S
и добавьте дополнительную цитату в начале и конце.
Смутно Связано: $* в Bourne Shell.
Некоторые фон
Напомним, что список аргументов main() - это C-ism и Unix-ism. Оболочка Unix/Linux (например, Bourne Shell и т.д.) Интерпретирует командную строку, исключает аргументы, расширяет подстановочные знаки, такие как *
, на списки файлов и передает список аргументов вызываемой программе.
Итак, если вы скажете:
$ vi *.txt
Команда vi видит, например, следующие аргументы:
vi
a.txt
b.txt
c.txt
d.txt
Это связано с тем, что unix/linux работает внутренне на основе "списка аргументов".
Windows, которая в конечном итоге получается из CP/M и VAX, не использует эту систему внутренне. В операционной системе командная строка представляет собой всего лишь одну строку символов. Ответственность вызываемой программы заключается в интерпретации командной строки, расширении файловых глобусов (*
и т.д.) И обработке нечетких цитируемых аргументов.
Итак, аргументы, ожидаемые C, должны быть взломаны библиотекой времени выполнения C. Операционная система предоставляет только одну строку с аргументами in, и если ваш язык не является C (или даже если он есть), он не может быть интерпретирован как аргументы, разделенные пробелами, указанные в соответствии с правилами оболочки, но как нечто совершенно иное.
Ответ 2
Вот пример того, как это может измениться.
Предположим, что у вас есть два исполняемых файла: 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/s/c), а не foo.exe
(как это происходит только с cmd/c). Поэтому одной из причин использования /s было бы, если вы хотите убедиться, что команда анализируется точно так же, как если бы она была введена в командной строке. Вероятно, это скорее всего будет желательным в сценарии в вопросе, связанном с Michael Burr, где cmd.exe запускается CreateProcess, а не из командного файла или самой командной строки.
То есть, если вы скажете
CreateProcess("cmd.exe", "cmd /s /c \"" MY_COMMAND "\"", ...)
тогда строка MY_COMMAND
будет анализироваться точно так же, как если бы она была введена в командной строке. Если вы берете ввод с командной строки от пользователя или если вы являетесь библиотекой, обрабатывающей командную строку, предоставляемую приложением, это, вероятно, хорошая идея. Например, функция C runtime library system() может быть реализована таким образом.