Комментарии 108
Но за статью спасибо, пишите еще: периодически приходится с такими скриптами сталкиваться, и обычно натыкаешься на что-то такое, от чего мозг взрывается.
Надо бы эти моменты записывать, но не всегда получается. В общем, наконец-то появится возможность формализировать претензии к такому синтаксису.
Боюсь нарваться на минусы. Но синтаксис почти всегда дело привычки и вкусовщина. К примеру, да у bash синтаксис вырвиглазный, но шелл всегда под рукой и логично его для мелких автоматизаций использовать и, со временем, к нему привык и беглый взгляд на скрипты сейчас не вызывает отторжения. С другой стороны, по мне, так в том же Rust и Go синтаксис тоже не менее вырвиглазный, но пока потребностей их использовать не возникало и при взгляде на исходники возникает ощущение отторжения, что не умаляет их прочих достоинств.
А вот коллеге — нравится синтаксис Rust. А баш вызывает реакцию, похожую на вашу :)
Вместо него лучше использовать более молодые скриптовые языки с нормальным синтакисом, контролем ошибок и отладчиками
Думаю если бы не распространненость никто бы и не юзал.
Я думаю, что вы еще просто не сталкивались с ситуациями, когда задачу надо решить минимальными средствами. в том числе с минимумом сторонних зависимостей.
Да, в баше много чего нет. Мне, например, для удобства пришлось самому реализовать передачу внутрь функций и обратно из функций массивов. Точнее, закостылить (порядка 30 строк на всё), но это точно лучше, чем тянуть десятки и то и сотни мегабайт для подобного готового в питоне или чем-то еще более монструозном.
Вообще, специфические инструменты — они для специфических применений. Те же init.d скрипты с минимальной логикой удобнее всего писать именно на баше, получая бонусом неплохую переносимость.
Так что я бы не рискнул сказать, что баш устарел. Может, он и не секси по нынешним временам, но по-прежнему полезен.
Что написано на баше можно запустить на любой никсовой машине без бубна.
Пишете скрипт на bash из под Centos 7.x, кидаете на Ubuntu и оказывается, что там bash линкуется на dash, и ключевого слова function для декларации функции в «даше» нету.
Потом кидаете этот же скрипт на солярис и выясняете, что версия там доступного баша не 4.х, а 3.х и что новые вкусности вроде associative array, которые вы с такой радостью использовали, не будут работать.
Потом кидаете этот же скритп на HPUX и оказывается что там баша из коробки нет вообще, а только sh и понятное дело полскрипта просто не срабатывает.
А дальше либо начинаются танцы с бубном с приведением баша до нужной версии на всех системах (а это не всегда возможно), либо приходится скрипт переписывать с учётом доступных вещей в версии 2.x — для полной обратной совместимости с sh, чтобы-таки работало везде (и то я побоюсь дать 100% гарантию).
Немного утрированно, но вполне себе реальная рабочая ситуация с которой я тоже сталкивался.
А после этого начинаются танцы с бубном с флагами для других программ, потому что они могут оказаться очень разными и порой один и тот же флаг делает разные вещи. Посмотрите, скажем, на netstat в Linux и BSD.
Добрый день.
Спасибо за ваш комментарий. Да, такая ситуация действительно возможна.
За время работы с удаленным сервером и на Ubuntu не было таких проблем. Даже больше, все скрипты, что приведены в статье работают в ConEmu и на Windows 10.
Но опять же, учитывая все те системы, что вы назвали, очень даже реальная ситуация.
На dash линкуется не bash, а /bin/sh.
Чтобы не быть голословным я сейчас специально скачал 16.04.1 посмотреть. Тут вы правы. Либо я подзабыл, либо это поведение изменили (на даш я натыкался лет 5 назад)
А если в скрипте используются специфические bash-фичи, то по крайней мере странно начинать его с #!/bin/sh
Из собствсенного опыта — многие «Шапочники», к сожалению, этим грешат, и вот почему:
user@server:[~]: cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.1 (Maipo)
user@server:[~]: stat -c %N $(which sh)
‘/usr/bin/sh’ -> ‘bash’
user@server:[~]: cat /etc/redhat-release
Red Hat Enterprise Linux Server release 6.5 (Santiago)
user@server:[~]: stat -c %N $(which sh)
‘/usr/bin/sh’ -> ‘bash’
На самом деле это недоработка Bash. Нужно напрячься и поискать пруфы, но вроде существует соглашение, если оболочка запускается симлинком с именем sh, то начинать в работать в режиме совместимости с классическим Shell. Тут как раз вопрос переносимости.
Кроме того, целью режима совместимости является запуск как можно бо́льшего числа POSIX‐совместимых скриптов, а не полная эмуляция POSIX shell. В идеале — все скрипты для POSIX shell запускаются и работают как в POSIX shell, а про несовместимые ничего не говорится — вполне могут и работать.
В zsh точно так же.
Чтобы понимать разницу между терминалом, эмулятором терминала, CLI и шеллом, и как оно всё взаимосвязано когда вы запускаете тот же ConEmu, советую покурить хотябы английскую википедию, там неплохо написано.
кидаете на Ubuntu и оказывается, что там bash линкуется на dash
стоп. Bash никуда не линкуется. А вот sh линкуется на dash по умолчанию и поэтому многие скрипты, которые пишут:
#!/bin/sh
а используют башизмы начинают обламываться. Но мне одному кажется, что это сродни использования, например, memfd и ругаться, что переносимость у C хреновая, когда на целевой OS (не Linux или Linux < 3.17) оно не заработало или начало валиться?
UPD: уже увидел обсуждение этого нюанса.
А вот что то посерьезнее — установщики, сложные бэкап скрипты, все что > 25 строк, я бы предложил Питон, D, Lua, или JScript (windows)
Про устаревание говорят те, кто по жизни забивает гвозди, пусть не микроскопом, так пассатижами просто потому, что они у них всегда в кармане лежат.
Добрый день.
Спасибо за ваш комментарий. Добавил в статью упоминание об этом.
а можно и без указания шела:
. ./script.sh
Нет, нельзя. Ни в коем случае не запускайте так скрипты: bash script.sh
запускается в отдельном процессе. Если скрипт для своих нужд перейдёт в другой каталог, добавит/удалит путей в $PATH
, изменит $IFS
или что‐то подобное и, разумеется, не восстановит состояние (разумеется — это же скрипт — оболочка, в которой он будет запущен, будет убита по окончанию скрипта), то с последствиями всего этого при использовании команды .
вам придётся иметь дело в своей более не уютной интерактивной сессии, т.к. скрипт будет запущен внутри этого процесса.
И ещё одно соображение: скрипт запускается с настройками, предназначенными для исполнения скриптов. А при использовании .
из интерактивной сессии будут использоваться интерактивные настройки, что может изменить поведение. В т.ч. активны alias
ы (обычно не особо проблемно, но если что‐то не так, то вы получите ошибку на ровном месте, а alias
ов у меня много, в т.ч. на распространённые вещи вроде alias cp='cp -iR'
).
Для начала нам нужно знать где находится bash. Эта информация нам понадобиться при написании самих скриптов. Чтобы узнать где находиться bash, выполните следующую команду:
which bash # где находится bash
Любой скрипт на bash должен начинаться со строки:
#!/bin/bash
Вопрос: ну и зачем вызывался which
?
Обработка аргументов внутри скрипта:
…
Куда делась $@
?
Первые три варианта схожи и каждая следующая конструкция дополняет предыдущую. Рассмотрим самый простой вариант:
if [[ condition ]] …
Такое описание if
мне категорически не нравится, оно предполагает, что [[ … ]]
является частью синтаксиса if
, хотя это совершенно не так. После if
идёт команда — любая. Упрощения неуместны, вещи вроде if grep 'foo' ../bar
встречаются слишком часто, чтобы это игнорировать и отложить «на потом». Аналогично с while
, здесь даже хуже: [в /usr/share/bash-completion] echo $[1.0 * $(ag 'if \[\['|wc -l)/$(ag 'if \w'|wc -l)]
даёт 6.3
(ваш вариант используется в шесть с лишним раз чаще), тогда как echo $[1.0 * $(ag 'while \[\['|wc -l)/$(ag 'while \w'|wc -l)]
даёт 0.74
([[
используется в 1,4 раза реже).
Добрый день, Николай.
Спасибо за ваш комментарий.
Вопрос: ну и зачем вызывался which?
Чтобы узнать где находится сам bash
Куда делась $@?
Обновил
Такое описание if мне категорически не нравится, оно предполагает...
Да с if, while
немного незадача вышла. Хотя на разных ресурсах предлагаю по-разному. И тот же Google рекоммендует if
в разных вариациях
Чтобы узнать где находится сам bash
А зачем это узнавать, если в первой строчке всё равно #!/bin/bash
? И оно должно так и оставаться, потому что это стандарт де‐факто. Даже если в вашем дистрибутиве /bin
— это ссылка на /usr/bin
и она отсутствует в $PATH по‐умолчанию (и, соответственно, which bash
выдаст не то).
Я это к тому, что вы предложили узнать, где bash, но дальше полученное знание нигде не используется.
Тут ниже говорят, что новым стандартом де‐факто должно быть #!/usr/bin/env bash
. Но и с ним which
не нужен.
На эту тему очень много неоднозначностей.
К примеру, это просто стечение обстоятельство, что на многих системах env лежит в /usr/bin/. Встречаются и такие, на которых /bin/env (мне какая-то сборка специализированная попадалась). Расположение этой команды не регламентирутся никакими стандартами, типа FHS.
Т.е. собственно на такой паттерн можно рассчитывать точно так же, как на /bin/bash.
Затем, это повод для вмешательств такого рода:
cd /tmp
touch bash
chmod +x bash
vim bash
export PATH=/tmp:$PATH
после чего, выполняя любой скрипт с #!/usr/bin/env bash
, он будет передаваться на управление не bash, а вашему скрипту/программе. С одной стороны — гибкость. С другой — уязвимость. Где-то тут на Хабре недавно эксплуатация этой особенности демонстрировалась.
Не получится с bash, подменят так mv. И вообще, если есть доступ к переменным окружения то можно и такое устроить:
env BASH_FUNC_echo%%='() { builtin echo vulnerable $@; }' bash -c 'echo abc'
Это я к тому, что никаких новых уязвимостей #!/usr/bin/env
не создаст.
Вы частично правы по поводу не используемых знаний. Но это больше мой недочет по тексту. На самом деле, полученная строка дальше и используется
Куда делась $@?
Обновил
Как раз вот
"$*" # все аргументы в виде одной строки (слова)
можно было бы и опустить: быстрое исследование ((cd /usr/share/bash-completion ; ag '\$(?:\{[#!]?)?\*')
) показывает, что во всём каталоге /usr/share/bash-completion $*
встречается ровно 1 (один!) раз — в строке 258
local items="${*}"
файла helpers/gentoo-common.sh. Ещё один раз в комментарии и два раза в виде \$*
(т.е., по сути, не переменной $*
). Заметьте: подсветка синтаксиса хабра даже не подсветила эту бесполезную вещь как переменную:
Вопрос: ну и зачем вызывался which?
Версия: Чтобы узнать где находиться bash и поместить его (если он не там) в /bin/bash?
Возможно. ;-)
И ещё: var1=$1
, [[ -f $1 ]]
, rm $1
и множество подобных — можете мне точно сказать, в каких случаях не нужно использовать ""
вокруг переменной и почему? Лучше сразу показывать новичкам безопасный код и писать кавычки просто везде, поскольку это проще, чем помнить, где их можно и не писать и исправлять опасные привычки.
Я надеялся что этот момент будет освещён.
Я 99% времени трачу потом на попытку хоть как-то расставить кавычки, что бы оно хоть как-то работало.
""
) при обращении к переменным. Это предотвратит интерпретацию специальных символов, которые могут содержаться в именах переменных, за исключением $
, `
(обратная кавычка) и \
(escape — обратный слэш).Но опять же, в данном, конкретном случае — это лишнее
При чём тут имена? Двойные кавычки нужны, чтобы файл с именем home
с именем malicious -rf
(с пробелом в конце) не привёл к удалению содержимого /home, когда вы будете писать rm $1
. Кавычки нужны, чтобы значения переменных оставались одним куском, имена тут ни при чём. И в данном конкретном случае это совсем не лишнее: во‐первых, писать кавычки нужно всегда, просто чтобы написать их и когда нужно. Во‐вторых, вы пишете rm $1
, причём $1
получен от пользователя. А если я хочу подобным скриптом удалить что‐то в ~/.wine/drive_c/Program Files
?
Ну почему bash?
В нём есть ряд забавных приколов, которые весьма удобны при программировании — и чего нет в sh/dash.
Да, и автор зря, пмсм — не указал вот эту замечательную книжку.
Хоть она и «advanced», но написано неплохо, и кривая освоения в ней достаточно плавная.
fish слишком ограничен. Если твоё понимание того, как должна вести себя консоль совпадает с авторскими и тебя устраивают урезанные возможности по написанию однострочников — то всё в порядке. Но с моей точки зрения это не «начинающий консолевод», а «я иногда немного пользуюсь консолью и не собираюсь пользоваться ею интенсивнее».
И я не знаю, с чего вы решили, что «поставить фиш не так сложно» — fish, вообще‐то, единственная оболочка, которой требуются runtime файлы (то, что в /usr/share/fish) для базовых возможностей (того же math
). Bash такое нужно только для автодополнения. Zsh — автодополнение и некоторые дополнительные возможности, но она вполне обходится и без них. Различным POSIX shell ничего вообще не нужно: продвинутого возможностей нет, даже более‐менее интелектуального автодополнения. Ну а там, где можно ставить fish/bash/zsh обычно установка любой из альтернатив — дело одного запроса пакетному менеджеру. Несмотря на требования наличия runtime файлов никаких трудностей ни с одной оболочкой я не испытывал, что ставя пакетным менеджером, что используя make install
для установки тестируемой версии в нестандартный (не /usr или /usr/local, а что‐то вроде ~/.local-fish) каталог.
И что такое «shell»? Вообще‐то это слово обозначает просто «оболочка» — класс программ, в который входят и zsh, и fish, и bash, и busybox, и dash, и много чего ещё.
2. фиш легче освоить так как там более понятный и привычный синтакисис, как минимум для программистов, я честно пользоватлся bash лет 12, и до сих пор не могу привыкнуть к его синтаксису, хотя мой юз-кейс ограничен гитом, cat и скриптами автоматизации максиму строк на 200-300.
3. Я не считаю что более сложные вещи, нежели то что можно уместить в 20-40 команд нужно писать на скрипте интерпретатора, поддерживать такое хозяйство тяжело, мне лично проще взять ruby или golang и накидать быстренько более сложную логику в виде пиложения: намного богаче набор библиотек, легко поддерживать и тд. Хотя сложные вещи пытался писать: системы сборки, тулчейны и деплой скрипты. Всё это геморойно, как по мне.
4. shell, я имею вввиду «sh» — Bourne shell.
- Тем, что чем больше файлов, тем больше потенциальных проблем. С моей точки зрения fish не отличается от zsh по сложности установки, но если бы меня спросили, какая оболочка должна была бы быть более сложной, то я бы назвал fish.
- Я не отрицаю, что он простой. Но ограниченный: Cannot save multi-line output in a variable — запросу уже четыре полных года. Я не могу нормально работать с таким языком, даже несмотря на то, что он понятнее zsh. А на zsh можно отлично писать write-only однострочники там, где в других оболочках пришлось бы писать скрипты.
Я тоже почти никогда не пишу какие‐то сложные скрипты для оболочки. А вот разные сложные однострочники (часто что‐то массово скачивающие из интернета) бывает — обычно что‐то, подо что perl теоретически подходит лучше, только zsh я знаю лучше. Иногда пишу автоматические тесты, но при большой сложности они переписываются на основном языке проекта.
Проблема в том, что для fish я писал в основном только powerline-setup.fish, и fish бесил меня даже в таком простом файле:
test
,env
,math
: создаётся впечатление, что у fish просто нет своих возможностей: лишние процессы на каждый чих (math
использует внешние программы).- Конструкция вида
(dirname (status -f))/../../../scripts/powerline-config
меня напрягает: я отлично понимаю, что теоретическиdirname
может вернуть имя каталога с новой строкой внутри. - Отлаживать совершенно невозможно: нет
set -x
.fish -d
выдаёт слишком много либо слишком мало информации, уровень выдачи информации не изменяется во время работы, на некоторые вопросы ответить по выдаче сложно или нельзя (пытался найти в логе пользователя, кто, где и почему изменяет fish_prompt — не нашёл ничего внятного). И да, если с установкой кучи runtime файлов проблем нет, то вот с тем, что они спамят выводfish -d
проблемы есть.
А она где‐то ещё используется? В linux дистрибутивах сейчас в качестве /bin/sh обычно либо bash, либо dash. Иногда busybox, но это больше для систем с ограниченными ресурсами. Теоретически ещё могут быть zsh, а также другие клоны bourne shell вроде posh. В целом это дело обычно называют «POSIX‐совместимыми оболочками» и предназначается исключительно для скриптов. Busybox ещё предполагает интерактивное исполнение, но вот у posh и dash оно скорее для галочки и нет даже автодополнения, поэтому игроками они считаться не могут.
В некоторых дистрибутивах (я использовал из них grml и babun (сборка cygwin)) используется предустановленный zsh. Ещё как‐то ставил на виртуалку FreeBSD для тестов, там tcsh в качестве интерактивной оболочки по‐умолчанию (скрипты на этом писать на порядок сложнее, чем на любом другом языке из семейства *sh, что я видел).
С тех пор всем советую, прежде чем к любому софту искать книги, курсы и прочий хлам, сначала read the fucking manual.
да уж, про условия в bash написано вообще ужасно. нет if grep, if [, только if [[.
остальное на совести автора.
Ну и понятно, всегда лучше поставить oh-my-zsh и не париться.
Oh-my-zsh имеет плохую репутацию у разработчиков самой zsh. Подробно можно расспросить на канале в freenode, но насколько я понял претензии такие: во‐первых, OMZ выполняет работу, которую уже выполняет zsh. Во‐вторых, когда что‐то идёт не так и пользователь приходит на канал, чтобы спросить совета, отлаживать OMZ на порядок сложнее.
Бессмысленно критиковать, не предлагая альтернативу. Если бы они предложили что-то более правильное и удобное, мы бы все уже перешли, включая авторов OMZ.
Спросите на канале. Я не использую OMZ или альтернативы (если они есть), мне достаточно того, что я могу настроить самостоятельно. Насколько я понял по обсуждениям, именно последнее и предлагается. Ещё в списке рассылки к менеджерам дополнений (не к сборкам как OMZ, а просто к очередным языкоспецифичным пакетным менеджерам) относятся достаточно лояльно (но их я тоже не использую).
Добрый день, Акжан.
Спасибо за ваш комментарий.
да уж, про условия в bash написано вообще ужасно. нет if grep, if [, только if [[.
В начале статьи есть раздел Важный момент. Сосбственно из-за этого и не упоминались все возможные варианты использования if
. Предполагается, что если читателю будет интересно, то он прочитает дополнительную информацию из ресурсов в "Полезных ссылках".
Привел пример синтаксиса, который использую ежедневно. Не испытываю проблем с написанием if [[ ... ]]
. Хотя тут во всех примерах if [ ... ]
. А тут в большинстве рекоммендаций используется вариант if [[ ... ]]
Ну и понятно, всегда лучше поставить oh-my-zsh и не париться.
Сарказм детектед или нет?
… чтобы генерировать скрипты service application command :)
Не более.
Python очень многословен на фоне bash. Не надо забывать, что сам по себе шелл довольно плох, но его в здравом уме и не используют для написания серьёзных программ. Он нужен как клей в unix среде и с этой ролью он справляется лучше чем python, поскольку имеет специально заточенные под это примитивы, типа перенапрвления потоков, опроса выходных параметров и управления фоновыми задачами. На python все это разумеется есть, но не на уровне примитивов.
Примеры:
1) Сохранить вывод программы в файл (>, grep, cut и т.д. по необходимости против ProcessOpener и работы с потоками вручную)
2) Скачать файл на диск (wget против urllib2 подключением ProxyHandler)
Роль клея ещё прочили тиклю. Но что то его не вспоминают сейчас, в отличие от питона.
А bash лучше применять с известной долей осторожности — современные условия могут потребовать больших переносимых скриптов, на которые он не проектировался.
$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
$ wget
-bash: wget: command not found
$
Ооопс. С коих пор wget стал bash'ем-то? =)
Вот потом и разгребай такие скрипты…
Переход на светлую сторону. BashПокайтесь, ибо грядёт Ansible с python'ом и j2 под капотом
Добрый день.
А можно более развернутый комментарий? А то не очень понятно, что вы хотели сказать
Вы собираетесь использовать Ansible в роли быстрого "однострочника" для запуска перла/грепа/авка/седа?
Извините.
Ну обычно баш — это конвеерная обработка много-данных грепами, седами, перлами, авками и прочими мелкими утилитами.
Зачем вы предлагаете использовать для этого ансибл — мне непонятно от слова совсем.
Ни о какой "Черной магии" не идет речь. "Светлая сторона" — это посыл всей серии статей про консоль.
А Ansible — имхо, то чем стоит сегодня заменять bash скрипты
Можно пруффы? А то только и слышу, что "bash ужастен...", "Он не годится..."
Чем лучше Ansible?
Ansible is a radically simple IT automation system. It handles configuration-management, application deployment, cloud provisioning, ad-hoc task-execution, and multinode orchestration — including trivializing things like zero downtime rolling updates with load balancers.
есть подозрение что вы путаете лопату и перфоратор, лопатой тоже стену можно пробить, но зачем?
Любой скрипт на bash должен начинаться со строки:
#!/bin/bash
Вообще говоря, лучше так не писать, за исключением
/bin/sh
, потому что bash
совершенно не обязан лежать в /bin
. В той же FreeBSD он ставится из портов совсем не в /bin
(возможно, что-то изменилось с моего последнего использования этой системы). А в скриптовых языках вроде python абсолютные пути (помимо того, что бинарь может лежать совершенно не там, где ожидает автор скрипта) еще и ломают virtualenv.Более универсальна форма записи:
#!/usr/bin/env bash
Лучше вообще не писать на баш с расчетом на кросиспользование с Freebsd, поскольку там будет куча проблем c совместимостию gnu и bsd утилит, а расчитывать на установленные порты это рисковано. Поэтому только голый sh, и максимально древние спеки sed, awk, grep.
Ну и во-вторых, ну ребят, ну все уже. Мне конечно ещё приходится иногда писать с учетом Unix/Aix/Solaris, но для большинства вопросы совместимости уже не стоят. Linux захватил Unix сервера прочно.
Добрый день.
Спасибо за ваш комментарий.
Более универсальна форма записи:
#!/usr/bin/env bash
Пытался найти пруффы на ваш комментарий тут и тут. Нет такого. Плюс ко всему, большинство литературы и статей, что читал и читаю по bash используют эту строку:
#!/bin/bash
Не будете ли вы так любезны поделиться ссылками, где подробно описано, зачем использовать именно такую форму записи?
Любой скрипт на bash должен начинаться со строки:
#!/bin/bash
Вроде как давно уже рекомендуется эта запись:
#!/usr/bin/env bash
Добрый день, Виктор.
Спасибо за ваш комментарий.
Выше в ответе на комментарий FFiX описал сиутацию, почем так. Повторюсь. С данной формой записи:
#!/bin/bash
за все время использования bash скриптов проблем не испытывал. Поделитесь ссылками, где описано, почему лучше писать:
#!/usr/bin/env bash
Чтобы к следующей статье я был более подготовлен и не использовал в своей работе устаревшие подходы и решения
Те скрипты, что приведены в статье работают на: Ubuntu, ConEmu, Windows 10, удаленный сервер.
быстрогугл: В чём смысл и преимущества #!/usr/bin/env?
Вот простой пример:
[user@server ~]$ uname -a
HP-UX server_name B.11.31 U ia64 redacted_machine_id unlimited-user license
[user@server ~]$ which bash
/usr/bin/bash
Сталкивался со случаями, когда в системе была одна версия баша/пайтона/перла, а для конкретного пользователя/задачи ставилась другая куда-нибуть в /opt, например просто потому что нет возможности поставить нужные библиотеки. Через environment variable можно тем самым для конкретного пользователя задать где валяется бинарка и иметь переносимый между системами (например dev и prod) код.
Г-н Borz уже успел скинуть ссылку на «стэк» постом выше.
var1=$1
var2=$2
Дальше читать не стал.
var1="${1}"
var2="${2}"
Добрый день, Владислав.
Спасибо за ваш комментарий. В данном конкретном примере это не критично. Что вас не устроило ?
Вообще‐то это проблема гигиены кода, отсутствие кавычек здесь не создаёт опасной ситуации, насколько я знаю. Я лично всё равно предпочту написать кавычки — это проще, чем закопаться в man bash
, чтобы подтвердить экспериментально проверенное отсутствие проблем. Но вот писать в кавычках ещё и фигурные скобки — зачем? Там текста дальше нет, будет текст — поправите, подсветка синтаксиса в редакторе не даст пропустить ошибку.
Консоль в массы. Переход на светлую сторону. Bash