LINUX.ORG.RU
ФорумTalks

Традиции командной строки


1

1

По традиции в командной строке спецсимволами (читай: дефисами) выделяются *ключевые слова* программы, а неключевые (типа имён файлов, регэкспов, чисел (в том числе отрицательных)) — нет. Хотя ежу ясно, что ввиду конечности ключевых слов, спецсимволами нужно маркировать *неключевые* слова.

# традиции
foo -key filename   # для защиты "от дурака" лучше даже `-key -- filename`
bar -key -- -42

# разум (тут в качестве спецсимвола взято двоеточие)
foo key :filename
bar key :-42

Как так получилось? Unix писали вроде бы умные люди, и закладывали традиции тоже они.

Перемещено post-factum из development


foo key :filename

Допустим, принимает список файлов, как передать все в текущей директории? Стало намного проще, неправда ли, прям заиграло!

anonymous ()

Хотя ежу ясно, что ввиду конечности ключевых слов

Не ясно, потому что несусветный бред без намёка на логику. При чём тут вообще конечность? На фоне разномастных просто-аргументов выделяются ключи, которые имеют особое значение и обрабатываются особым образом. Особые вещи логично выделять особым символом. А обычные логично не выделять, тем более что это просто неудобно, учитывая каким огромным множеством способов этот список аргументов можно составить.

slovazap ★★★★★ ()

Традиции: совершить foo (используя key) над filename.

Разум: совершить foo используя key (над filename).

schizoid ★★★ ()
Ответ на: комментарий от anonymous

Допустим, принимает список файлов, как передать все в текущей директории?

Несложно придумать что-нибудь. В традиционном синтаксисе тоже много косяков. Вопрос темы был в другом: почему *первоначально* выбрано такое поведение.

toady2 ()

ежу ясно

А человеку должно быть ясно, что выделять нужно именно ключи, потому что их конечное количество и они фиксированы, то есть заранее известны. Сами имена файлов могут быть подставлены из wildcards (например, gcc -c *.c), возвращены другой $(программой) или взяты из ${переменной}.

quasimoto ★★★★ ()
Ответ на: комментарий от slovazap

Под ключевыми словами я имею в виду какие-то постоянные строки, составляющие «язык» программы. Неключевые — это все остальные слова, которые пользователь передаёт в качестве данных. Под «конечностью», как нетрудно понять, подразумевалось, что ключевых слов не слишком много, в отличии от произвольных строк (если абстрагироваться от ограничений реалий и предполагать, что аргументом может быть любая строка, то неключевых слов, действительно, будет бесконечное число).

Если целью вашего буквоедства было повышение ЧСВ, то прошу закончить наш диалог.

toady2 ()
Ответ на: комментарий от quasimoto

Сами имена файлов могут быть подставлены из wildcards (например, gcc -c *.c), возвращены другой $(программой) или взяты из ${переменной}.

Уже ответил. Конкретнее, можно, например, добавить *ключевое слово* '--', означающее «все следующие аргументы являются неключевыми словами»

gcc -- *.c

что выделять нужно именно ключи, потому что их конечное количество и они фиксированы, то есть заранее известны.

Не понял логической цепочки. Ключевые слова являются подмножеством неключевых (как строки). От того, что мы добавим к ключевым какие-то спецсимволы ситуация не изменится. А вот, ежели наоборот будет действовать, то изменится (надо лишь договорится, что ключевые слова со спецсимвола никогда не начинаются).

toady2 ()
Ответ на: комментарий от toady2

P.S. Повторю *ещё раз*, что целью темы не сравнение традиционного с «разумным» подходом, а выяснение, почему изначально был выбран традиционный. Создатели unix не могли не понимать, что дефисы перед ключевыми словами лишь уменьшают вероятность коллизий, но не исключают её (в то время как дефисы перед неключевыми — исключают).

toady2 ()
Ответ на: комментарий от toady2

Если имя программы - foo, параметр - bar (начинается с — или нет - неважно), имена файлов - a, b, c, то классическому шелу чтобы составить аргументы для exec* нужно только склеить эти строки, может, проэкранировать что-то. Альтернативному нужно (непонятно зачем) проставить двоеточия перед a, b и c. Но зачем? Ну и потом, значением ключа может быть произвольный текст - имя файла, процесса, число, ну и просто текст вообще (foo --bar blah : blah # blah), так что разумно передавать просто текст без присказок в виде двоеточия (но с возможностью заключить в кавычки и проэкранировать символы), а вот ключ нужно как-то синтаксически выделит, потому что, да, это ключевое слова шела и оно должно отличаться от всего остального текста, который (текст) и является основным и единственным типом для языка. Как выделять, в общем-то, не важно - можно и двоеточием (gcc :c *.c).

quasimoto ★★★★ ()
Ответ на: комментарий от toady2

исходно была позиционая привязка

затем удобно оказалось иметь именованые аргументы - затем это редуциоровалось если аргумент начинается особым образом то дальше идёт имя и возможное значение либо указания только имени известным образом меняет функцию которая указана первым аргументом и которую обрабатывает обработчик терминала ( терминалы были медлеными и поэтому базовые команды такие криптик)

qulinxao ★★☆ ()
Ответ на: комментарий от toady2

Не-не, вы не поняли меня.

Твой вброс неинтересен оказался, смирись.

schizoid ★★★ ()

для лучшего прояснения рой историю sh и её предшествеников

там обнаружиш что первоночальной средой был ed в котором и творили. для запуска используя !

qulinxao ★★☆ ()
Ответ на: комментарий от toady2

почему изначально был выбран традиционный

Помимо того, что пара «синтаксически выделенный ключ» + «просто значение(я)» лучше пары «просто ключ» (?) + «декорированное значение(я)», получается банально короче - параметров немного, их часто можно склеить в один (ps -a -u -x = ps -aux = ps aux), а прочих значений часто больше (много имён файлов, например, неудобно их все выделять).

quasimoto ★★★★ ()
Ответ на: комментарий от toady2

А в нормальном ЯП вообще нет коллизий, но зато писать приходится больше и нуднее.

quasimoto ★★★★ ()
Ответ на: комментарий от qulinxao

Ваш беспунктационный текст не осилил мой парсер. Но основные моменты уловил. Спасибо. Вы первый, кто ответил ровно на то, что я спрашивал.

toady2 ()
Ответ на: комментарий от toady2

Не-не, вы не поняли меня.

Я понял. foo bar :a :b :c :bar исключает коллизии, тогда как в foo --bar --bar коллизия возникает.

quasimoto ★★★★ ()
Ответ на: комментарий от toady2

целью темы не сравнение традиционного с «разумным» подходом, а выяснение, почему изначально был выбран традиционный

Вам, возможно, это удивит, возможно даже слегка раздосадует, но тему определяют скорее участники дискуссии, а не какой-то там унылый топик-стартер.

anonymous ()
Ответ на: комментарий от quasimoto

А в нормальном ЯП вообще нет коллизий, но зато писать приходится больше и нуднее.

На самом деле связи почти нет. В любом случае, можно избавится от коллизий в «традиционной» схеме без потери краткости.

Конечно, трудно рассуждать, когда традиционный стиль намертво вшился в мозги. Все люди инерционны к переменам и инакомыслию. Но, думаю, если бы мы с чистой головой сели разрабатывать безколлизионный, краткий и простой язычок для командной строки, то у «разумного» формата было бы больше шансов пройти отбор.

toady2 ()
Ответ на: комментарий от toady2

Но, думаю, если бы мы с чистой головой сели разрабатывать безколлизионный, краткий и простой язычок для командной строки, то у «разумного» формата было бы больше шансов пройти отбор.

Он повиснет в инфраструктурном вакууме, потому что большинство программ которые дёргает шел хотят параметры с -/--, то есть можно начать выделять как-то значения параметров и текст, но при этом стандартным программам всё равно придётся отдавать выделенные параметры - профита никакого. Так придётся переписывать весь base system с тулчайном, либо городить обвёртки.

quasimoto ★★★★ ()
Ответ на: комментарий от quasimoto

Я вас понимаю и полностью согласен. Ничего менять не надо, уже поздно. Вопрос был, почему в первоначальном отборе победил «традиционный» стиль.

toady2 ()

а как насчёт?

dd if=file of=out bs=1K

invy ★★★★★ ()
Ответ на: комментарий от toady2

Вопрос был, почему в первоначальном отборе победил «традиционный» стиль.

Потому что это проще. Например, есть программа с CLI, она смотрит свои char **argv в цикле, если видит argv[0] == '-', то трактует это как параметр. Альтернативно, ей бы пришлось трактовать argv[0] == ':' как значение, в случае значений для имён файлов это немного не нормально, потому что файл называется не так - нужно делать strcpy или использовать &argv[1].

quasimoto ★★★★ ()
Ответ на: комментарий от toady2

Я уже читал эту чушь про ключевые - не ключевые. Я вам повторяю - у вас неправильно работает мозг. Хотите закончить диалог - начните с себя.

slovazap ★★★★★ ()
Ответ на: комментарий от quasimoto

Хотя, почему бы не

ls h a l / ./
ls hal / ./
cp update Rv ./foo ./bar

разве что нельзя делать

ls foo bar
cp foo bar

нужно

ls ./foo ./bar
cp ./foo ./bar

в остальном парсить argv так же просто - файлы это то что начинается с / и ./, а всё остальное - параметры.

Сам шел не должен чего-то подставлять, так как разные программы по-разному парсят argv (par=val, cmd par val, --par val, -pars vals и т.д., наличие коллизий зависит, в общем-то, от самих программ а не от шела), он должен только правильно раскрывать свои */${}/$(), экранировать, составлять argv и вызывать exec*.

quasimoto ★★★★ ()
Ответ на: комментарий от quasimoto

есть работающие примеры

$ px ax
$ unrar x filename
$ 7z b
И «парсить» это сильно сказанно. Такое вообще руками писать не надо... отсюда кстати и растут ноги у традиции - getopt :D

invy ★★★★★ ()

ежу ясно, что ввиду конечности ключевых слов, спецсимволами нужно маркировать *неключевые* слова.

Ежи-мутанты на моем ЛОРе?

tailgunner ★★★★★ ()
Ответ на: комментарий от invy

есть работающие примеры

ps не файловая команда. А вот unrar - да, пример.

Такое вообще руками писать не надо... отсюда кстати и растут ноги у традиции - getopt

Это спорно. Я как-то не особо замечал использования getopt в проектах которые видел, чаще руками парсится (while / цепочка if / сравнение знаков argv / strcmp / присвоение значений выставленным параметрам (переменным) и т.п.).

quasimoto ★★★★ ()

Ты хоть букварь осилил, школота, перед тем как здесь «умничать»?

anonymous ()

Ежу ясно, что маркировку надо вешать на те классы аргументов, которые пользователь пишет реже. А так как программы проектируются так, чтобы в большинстве случаев не нужно было указывать ни одного ключа (Ну хорошо, так писались программы в ЮНИКСе. Сейчас все эти pacman и emerge пишутся немного подругому, но и в них неключевых аргументов больше, а значит этот класс аргументов маркировке не подлежит) то класс ключевых аргументов используется намного реже чем класс неключевых.

kim-roader ★★ ()
Ответ на: комментарий от toady2

прерву-ка я свое молчание

дефисы перед ключевыми словами лишь уменьшают вероятность коллизий, но не исключают её (в то время как дефисы перед неключевыми — исключают).

да

если у тебя будут претензии к синтаксису или семантике языков программирования примерно того же уровня продуманности — пожалуста, информируй меня о них (впрочем, если они у тебя появляются только на ЛОРе и только в темах, то я могу отслеживать твои темы)

можешь постучаться ко мне в жаббер для обсуждения аналогичных претензий

Создатели unix не могли не понимать, что дефисы перед ключевыми словами лишь уменьшают вероятность коллизий, но не исключают её (в то время как дефисы перед неключевыми — исключают).

я не думаю, что выяснение «но почему же создатели unix все-таки так сделали» имеет смысл... хотя и можно спросить на stackoverflow скажем, если очень хочется

вообще, *с высоты современности*, язык sh и традиции вокруг него — это угрюмое говно; как его сделать удобным — это интересная тема для обсуждения

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от toady2

Он повиснет в инфраструктурном вакууме,

нет

потому что большинство программ которые дёргает шел хотят параметры с -/--

да

Я вас понимаю и полностью согласен. Ничего менять не надо, уже поздно.

нет

дело в том, что

1. «инфраструктура» не так уж и велика для каждого конкретного юзера (скажем, со сколькими программами работаешь лично ты?)

2. программы можно пропатчить так, чтобы их обычная версия /usr/bin/foo разбирала аргументы, как обычно, ограниченные минусом, а особая версия (как пример, но не обязательно, хардлинк на обычную версию вида /usr/bin/new_system___foo) разбирал(а) аргументы по-человечески

3. шелл может знать, какой тип аргументов нужен программе, и при необходимости преобразовывать новый формат в старый формат, заодно избегая косяков вида rm -f вместо правильного rm — -f

www_linux_org_ru ★★★★★ ()
Ответ на: комментарий от toady2

Уже ответил. Конкретнее, можно, например, добавить *ключевое слово* '--', означающее «все следующие аргументы являются неключевыми словами»

gcc — *.c

#make для слабых духом
for i in *.c; do cc "$i" -o "build-`date`/`echo $i|sed 's/\.c$//'`"; done

Конда переведёшь это на свой синтаксис, тогда и поговорим. Тут ключ между именами файлов, да.

x3al ★★★★★ ()
Ответ на: комментарий от x3al
for i in *.c; do cc :"$i" o :"build-`date`/`echo :$i|sed :'s/\.c$//'`"; done
anonymous ()
Ответ на: комментарий от x3al
for i in *.c; do
  cc :"$i" o :"build-`date`/`echo :$i|sed :'s/\.c$//'`"
done
anonymous ()
Ответ на: комментарий от x3al

едрен батон, но неужели так трудно понять, что сказал ТС? обезьяну можно научить переделывать старый синтаксис в новый.

anonymous ()
Ответ на: комментарий от anonymous

:«$i»

:$i

Найди два отличия. Да, они существенны.

Вопросы остались? В *sh и без подобных заворотов с экранированием дофига рутины.

x3al ★★★★★ ()

кури букварь про слово «опционально».

Не понял? Объясняю:

cp source target

копирует source в target. В качестве источников может быть несколько файлов, в качестве приёмника может быть каталог, или файл. Это базовый функционал.

Опционально можно написать

cp -i source target
тогда утилита будет спрашивать, надо-ли переписывать файл, если он уже есть. Что-бы отличить опции от параметров ставится минус.

Если утилита напрямую с файлами обычно не работает, то минус не нужен, например

tar cz
hg commit
sed =
и т.д.
drBatty ★★ ()

Я думаю, что в повседневных операциях (cd, cp, mv, ls, vim, grep, (u)mount, &c.) чаще встречаются ситуации когда указан один или два аргумента --- файла. Ситуации при которых надо задать опцию программе встречаются реже.

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

Так же хочу напомнить, что программы GNU принимают опции в длинной нотации, которые можно записывать как --key -42 или --key=-42.

ssvda ()
Ответ на: внезапно от anonymous

Хочешь сказать, что тебе нравятся вложенные одинаковые кавычки? С экранированием? На пустом месте? Скриптописатели очень любят таких, как ты. Если поймают.

В том виде, как там есть, при имени файла «foo bar.c» оно сделает echo :foo bar.c; echo ругнётся на неизвестный ключ bar.c (у echo есть ключи с тех времён, как оно стало гнутым). Без двойных кавычек ты это не обойдёшь. А пример достаточно примитивный и стандартный. Вывод: этот синтаксис ещё хуже, чем текущий башевый → всё правильно сделали.

x3al ★★★★★ ()
Ответ на: комментарий от x3al

вы видели мое прошлое сообщение вам?

anonymous ()
Ответ на: комментарий от anonymous

пардон, оно почему-то не ооправилось

я говорил, что двоеточие необходимо только в случае, если возникают коллизии. если у echo нет ключевого слова bar.c, то он должен считать его неключевым. поэтому все cp, rm и пр. с вменяемыми именами файлов будут работать как и раньше.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.