Задача : написать один файл сценария, foo.cmd
который можно вызвать из командной cmd.exe
строки Windows (не PowerShell, не в режиме администратора), чтобы выполнить произвольный специфичный для Windows код ...
> .\foo.cmd
Hello Windows!
... но также может быть вызвана неизменным из типичного POSIX-совместимой (Linux / OSX) приглашение оболочки ( bash
, tcsh
или zsh
), чтобы выполнить произвольный POSIX-специфический код:
$ chmod a+x foo.cmd
$ ./foo.cmd
Hello POSIX!
... без необходимости установки или создания сторонних переводчиков / инструментов.
Я знаю, что это возможно, но с помощью cruft (то есть в Windows одна или две строки мусора / сообщения об ошибке выводятся в stderr или stdout перед «Hello Windows!»).
Критерием выигрыша является минимизация (первого) количества линий крафта и (второго) количества символов крафта.
Cruft может быть определен как любой вывод консоли (stdout или stderr), который не создается (произвольным) кодом полезной нагрузки. Пустые строки учитываются в количестве строк. Новые строки не учитываются при подсчете символов. Баллы по фрифту должны суммироваться на обеих платформах. Давайте не cls
будем обращать внимания на такие механизмы, которые сметают сумасшествие, но за счет того, что также удаляются предыдущие результаты терминала. Если Windows повторяет ваши команды, потому что вы еще не включили @echo off
, давайте исключим символы, которые она тратит на печать текущего каталога и приглашения.
Вторичным критерием является простота / элегантность решения внутри foo.cmd
: если «инфраструктура» определяется как любой символ, непосредственно не участвующий в произвольном коде полезной нагрузки, то сначала минимизируйте количество строк, содержащих символы инфраструктуры, а затем - общее количество инфраструктуры. персонажи.
Дополнительные похвалы, если POSIX-часть будет работать, несмотря на то, что в файле есть окончания CRLF! (Не уверен, что последняя часть даже возможна.)
Мое существующее решение, которое я опубликую здесь, как только у других появится возможность, использует 6 строк кода инфраструктуры (52 символа без учета новых строк). Он выдает 5 строк Cruft, две из которых являются пустыми, и все они происходят в Windows (30 символов, исключая символы новой строки и исключая текущую строку каталога / приглашения, которая появляется в двух из этих строк).
Ответы:
0 линий, 0 символов, 2 инфра. линии, 21 ниже chars, CRLF ок
Убрал другое решение.
Использование 17 символов
exit /b
из ответа Digital Trauma:источник
: command not found
когда в полезную нагрузку posix закрадывалась пустая строка, но я наконец понял, что речь идет не о:
первой строке, а о том, что CRLF не защищены#
. Для меня стало новостью, что#!
линия не нужна - это было причиной двух строк Windows Cruft в моей предыдущей версии.: ` >&3` \
в каждую строку полезной нагрузки, я думаю, вы могли бы сказать, что ее инфраструктурная стоимость произвольно высока.#
?Наберите 0 крафт + 4 инфра линии + 32 инфра персонажа. LF & CRLF ОК.
Это основано на том, что я нашел в этом блоге , с битами Amiga и другими ненужными строками. Я спрятал строки DOS в закомментированных кавычках вместо использования
\
продолжения строки, чтобы это могло работать как с CRLF, так и с LF.С окончаниями строк DOS CRLF или * nix LF он работает в Ubuntu, OSX и wine:
Чтобы создать это точно (с CRLF) на машине * nix (включая OSX), вставьте в терминал следующее:
источник
dosix
это тоже хорошее имя. Но на моем Mac (OS 10.9.4, Darwin Kernel Version 13.3.0, GNU bash версия 3.2.51) он не работает с:./dosix.cmd: line 13: syntax error: unexpected end of file
Есть идеи почему?Я уже опубликую решение, которое я использовал, так как оно уже побито. Это любезно предоставлено моим коллегой, который, я думаю, прочитал ту же запись в блоге, что и Digital Trauma .
#!
строке интерпретатор не заботится (поэтому для стандартных интерпретаторов, таких какsh
и друзья, он не работает)источник
#!
, что означает, что ваш единственный ответ на данный момент является действительным сценарием в системе POSIX. Конечно, некоторые другие могут работать, если - но только если они запускаются из оболочки с обходным решением для неисправных сценариев.#!
которыми я работал, имеют обходной путь для пропущенной строки, но они будут использовать разные оболочки для интерпретации сценария. Это означает, что «скрипт», который не начинается с,#!
должен быть действительным не только в одной оболочке, но и в каждой оболочке, которую он мог бы интерпретировать. Но что еще хуже, он работает только при запуске из другой оболочки. Такой скрипт может работать из командной строки, но не в контексте, где вы, наконец, намереваетесь его использовать.#!
строку в моем отредактированном ответе (1 строка инфраструктуры с 21 символом) можно объединить с ответом кого-либо еще при стоимости обработки только для Windows 2 строки (из которых одна пустая) или 23 символаРезюме / обобщение ответов и обсуждение
Это было весело, и я многому научился.
Некоторое несоответствие, связанное с Windows, неизбежно, если в вашей системе POSIX вам нужно запустить скрипт со
#!
строкой. Если у вас нет другого выбора, кроме как сделать это, то эта строка:это, вероятно, лучшее, что он может получить. Это приводит к выводу одной пустой строки и одной строки Cruft на консоль Windows. Тем не менее, вы можете обойтись без
#!
строки: в большинстве систем один из обычных интерпретаторов оболочки завершит выполнение сценария (проблема в том, что не всегда предсказуемо, какой интерпретатор будет - это зависит, но будет не обязательно должен быть идентичным оболочке, которую вы используете для вызова команды).Помимо этой хитрой первой линии, было несколько действительно гениальных бесцельных решений. Победившее представление от jimmy23013 состояло только из двух коротких линий инфраструктуры и использовало двойную роль
:
персонажа для реализации «тихой» линии на обеих платформах (как де-факто без участияsh
и в друзьях, и как ярлык маркер вcmd.exe
):Это есть возможность сделать такой запустить скрипт на системах POSIX , даже несмотря на CRLF линии окончаний, но сделать это для большинства переводчиков вы должны закончить каждую строку вашего раздела POSIX (даже пустые строки) с комментарием или символом комментария.
Наконец, вот два варианта решения, которое я разработал, основываясь на мнении каждого. Они могут быть чуть ли не лучшими из всех миров, поскольку сводят к минимуму ущерб от отсутствия
#!
и делают CRLF-совместимость еще более плавной. Необходимы две дополнительные линии инфраструктуры. Непредсказуемая оболочка POSIX должна интерпретировать только одну (стандартизированную) строку, и эта строка позволяет вам выбрать оболочку для остальной части сценария (bash
в следующем примере):Отчасти красота этих решений heredoc заключается в том, что они по-прежнему устойчивы к CRLF: до тех пор, пока они находятся
<<:Z
в конце строки, процессор heredoc будет фактически искать и обнаруживать токен:Z\r
В завершение вы можете избавиться от этих надоедливых комментариев в конце строки и при этом сохранить устойчивость к CRLF, удалив
\r
символы перед передачей строк в оболочку. Это немного увеличивает доверие к непредсказуемой оболочке (было бы неплохо использовать{ tr -d \\r|bash;}
вместо нее,(tr -d \\r|bash)
но фигурные скобки имеют синтаксис bash-only):Конечно, этот подход жертвует возможностью транслировать ввод stdin в скрипт.
источник