Что такое…

Одинарные или двойные кавычки в терминале — и куда пропали 5 долларов

Иллюстрация: две банки — закрытая хранит карточки как есть, а в открытую сыплются монеты и подменяют часть карточек

Попробуй в терминале:

echo "Скидка $5 сегодня"

Получишь Скидка сегодня. Пять долларов исчезли. Без ошибки, без предупреждения.

Теперь то же с одинарными кавычками: echo 'Скидка $5 сегодня'. Всё на месте.

В Python или JavaScript разницы между ' и " почти нет. В терминале это два разных инструмента. Перепутаешь — и команда сделает не то, причём молча.

Главное отличие в одной фразе

  • Одинарные кавычки '...' — «бери буквально». Внутри не происходит ничего: $, !, \, обратные кавычки — просто символы.
  • Двойные кавычки "..." — «склей в одну строку, но подставь значения». Внутри работают $ПЕРЕМЕННАЯ, $(команда) и, в интерактивном терминале, !.

Обе защищают от разрезания по пробелам. Это общее. Разница — в том, что происходит со спецсимволами внутри.

Сравнение по пунктам

$ — подстановка переменных.

  • '...': остаётся символом. '$HOME' — это пять букв.
  • "...": подставляет значение. "$HOME" — это /home/me.

Отсюда пропавшие доллары: $5 — это пятый аргумент скрипта. В терминале он пустой, его и подставило.

$(...) — результат команды.

  • '...': не выполняется.
  • "...": выполняется. "Сегодня $(date +%F)" вставит дату.

! — повтор из истории.

  • '...': просто восклицательный знак.
  • "...": в интерактивном bash и zsh работает как команда истории. echo "Готово!!" напечатает не «Готово!!», а «Готово» плюс твою предыдущую команду. Одиночный ! в конце строки обычно безопасен, а !! и !слово — нет.

\ — экранирование.

  • '...': обратная косая — обычный символ. Экранировать внутри одинарных кавычек нельзя вообще ничего.
  • "...": экранирует четыре символа: $, ", \ и обратную кавычку. "цена \$5" спасёт доллары.

Пробелы.

  • Обе одинаково защищают: "my file.txt" и 'my file.txt' — один аргумент, а не два. Про то, как без кавычек ломаются имена с пробелами, есть отдельный разбор — почему скрипт ломается на пробелах.

Где это стреляет в реальной работе

Коммиты. git commit -m "Починил $PATH в конфиге" — и в историю уйдёт весь твой PATH вместо слова. Сообщения с $ и ! пиши в одинарных кавычках. Это касается и агентов: если Claude Code или Codex собирает команду с текстом, именно здесь чаще всего бьётся сообщение.

JSON в curl. JSON внутри полон двойных кавычек, поэтому снаружи нужны одинарные:

curl -X POST https://api.example.com/users \
  -H 'Content-Type: application/json' \
  -d '{"name": "Ann", "role": "admin"}'

Но если нужно вставить переменную — внутри одинарных она не сработает. Приём: закрыть одинарные кавычки, вставить переменную в двойных, открыть снова:

-d '{"name": "'"$NAME"'"}'

Выглядит как азбука Морзе, но работает: три кусочка склеиваются в одну строку. Когда JSON больше пары полей, надёжнее собрать его через jq -n --arg name "$NAME" '{name: $name}' или heredoc.

Регулярки, awk, sed. Там много $ и \, которые должны дойти до программы нетронутыми. Почти всегда — одинарные: awk '{print $2}'. В двойных $2 превратится в пустоту ещё до awk.

Переменные в скриптах. Тут наоборот: "$FILE" и "$@" — всегда в двойных. Значение подставится, и пробелы в нём не разрежут аргумент.

Как вставить одинарную кавычку внутрь одинарных

Никак — экранирование внутри не работает. Но можно схитрить двумя путями:

echo 'it'\''s'      # закрыть, экранированная ', открыть
echo $'it\'s'       # особые кавычки $'...' понимают \' и \n

Второй вариант, $'...', полезно знать и для переносов: echo $'строка 1\nстрока 2'.

Как увидеть, что дойдёт до программы

Гадать не нужно — есть команда-рентген. printf печатает каждый аргумент в своих скобках:

NAME="Ann Lee"
printf '[%s]\n' $NAME      # [Ann] и [Lee] — два аргумента
printf '[%s]\n' "$NAME"    # [Ann Lee] — один
printf '[%s]\n' '$NAME'    # [$NAME] — буквально

Поставь printf '[%s]\n' перед любым хитрым куском — и сразу видно, сколько аргументов получится и что в каждом. Это быстрее, чем запускать настоящую команду и разбираться, почему она удалила или отправила не то.

Кому что подойдёт

Без «зависит от ситуации» — вот правило, которое закрывает 95% случаев:

  • Текст, который должен дойти буквально — сообщения коммитов, JSON, регулярки, awk/sed, пароли со спецсимволами — одинарные.
  • Всё, где есть твоя переменная или команда — двойные, и переменную оборачивай в них всегда, даже если «там точно без пробелов».
  • Сомневаешься — начни с одинарных. Худшее, что случится: переменная не подставится, и ты сразу это увидишь. С двойными ошибка бывает тихой: пропал кусок текста, а команда «успешно» отработала.

В zsh на Mac всё так же?

Да, правила те же: одинарные — буквально, двойные — с подстановкой, !! в двойных тоже раскрывается. В PowerShell на Windows логика похожая, но экранирование другое — там это обратная кавычка.

А в Python и JavaScript есть такая разница?

В Python нет: 'a' и "a" одинаковы. В JavaScript подстановку делают обратные кавычки: `Привет, ${name}` — по смыслу это ближе к двойным кавычкам терминала.

Учись вайб-кодингу, а не просто читай о нём

Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.

Открыть приложение
Робот KODiQ

ИИ-редактор KODiQ. Пишет про вайб-кодинг и AI-инструменты простым языком — каждый день.

Все статьи →