Двоеточие в шелле: команда, которая ничего не делает, но нужна
Знаешь, что меня зацепило вчера в одной статье? Автор рассказывает про команду :, которая буквально ничего не делает. Просто принимает аргументы, тут же их забывает и закрывает тему с кодом выхода 0 (успех). Звучит бессмысленно, правда?
Но подожди.
Что за двоеточие?
Двоеточие — это встроенная команда (builtin, то есть команда, вшитая прямо в оболочку) под названием null-command. Встречается в любом шелле: sh, bash, zsh — везде работает одинаково.
: аргументы... # делает ровным счётом ничего
echo $? # выводит 0
Появилась эта штука ещё в 1971 году в Thompson Shell — одной из первых оболочек Unix. Двоеточие тогда использовалось даже как метка для перехода (типа современных goto).
Зачем использовать команду-"пустышку»?
Вот тут начинается магия. Двоеточие бесполезно само по себе, но оно решает конкретные проблемы:
Проверка обязательных аргументов
Обычный подход — целый if:
if [ -z "$1" ]; then
echo "передайте аргумент" >&2
exit 1
fi
А теперь посмотри на это:
: "${REQUIRED_ARG:?передайте аргумент}"
Раскрытие параметров (parameter expansion) ${переменная:?сообщение} означает: если переменная пуста или не существует — выведи сообщение в стандартный поток ошибок и завершись с ошибкой. Двоеточие перед ним нужно, чтобы шелл не пытался выполнить результат как команду.
Короче? Четыре строки превращаются в одну.
Установка значений по умолчанию
: "${DATA_DIR:=/var/data}"
Аналогично предыдущему, но вместо ошибки подставляет значение справа от =. Теперь DATA_DIR всегда существует, а ты не писал DATA_DIR="${DATA_DIR:-/var/data}" отдельно.
Разница в том, что второй вариант создаёт новую переменную (если DATA_DIR не существовала), а ${VAR:-default} — просто подставляет значение, но не меняет саму переменную. С двоеточием и := ты именно присваиваешь.
Перенаправление файлов
: > error.log # очистить файл
: > error.log > access.log # очистить два файла
Команда-пустышка слева — просто чтобы шелл понял, что делать с операторами >. Без неё пришлось бы использовать true или echo -n.
Проверка доступности файлов
( : < config.json ) && echo "читаемо"
( : >> result.json ) && echo "записываемо"
Скобки создают подпроцесс. Если файл можно открыть для чтения или записи, : сработает. Если нет — команда упадёт, и && не выполнится.
Перехват сигналов
trap : INT # при нажатии Ctrl+C — ничего не делать
Полезно, когда не хочешь прерывать скрипт, но нужно, чтобы он реагировал на сигнал. trap требует команду — : идеально подходит как заглушка.
РАСКРЫТИЕ ПАРАМЕТРОВ С ДВОЕТОЧИЕМ
─────────────────────────────────
┌─────────┐
│ ввод │ : "${VAR:?ошибка}"
└────┬────┘
│
▼
┌───────────────────┐
│ VAR установлена? │
└────┬────────┬────┘
│да │нет
▼ ▼
"ничего" ошибка → stderr
не делать exit 1
Когда это не нужно
Личный выбор и читаемость — главные критерии. Если в твоей команде : вызывает вопросы у коллег, лучше написать if [ -z "$VAR" ]. Это не магия, а инструмент.
Автор статьи приводит пример из комментариев: один разработчик использует : как EDITOR в Git для автоматического сквоша коммитов при интерактивном ребейзе:
git -c sequence.editor=: rebase --interactive
Элегантно, но не сразу очевидно. Объясни команду в комментарии, и всё ок. Не объясни — станешь тем, кто оставляет загадки в коде.
Практический вывод
Двоеточие — это не хак и не обфускация. Это штатный инструмент POSIX, который решает конкретные задачи:
- Одна строка вместо четырёх при проверке аргументов
- Гарантированное присваивание значений по умолчанию
- Чистый no-op там, где команда обязательна по синтаксису
Используй там, где это упрощает код. Не используй там, где это добавляет загадок без причины.
Как и с любым приёмом — чувство меры решает.
Ссылки
- Статья Filip Roséen — A shell colon does nothing. Use it anyway — материал о том, зачем в shell нужна команда
:
Дмитрий Полухин — продуктовый дизайнер. Пишу про разработку, AI и дизайн интерфейсов. Обо мне, контакты и профили.