Сократить URL из терминала можно одной строкой:
curl -s -X POST https://api.elido.app/v1/links \
-H "Authorization: Bearer $ELIDO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"destination_url":"https://example.com/spring-sale"}' | jq -r .short_url
Она выводит https://s.elido.me/ab12cd и больше ничего. curl выполняет запрос, jq извлекает одно поле из JSON, а -r убирает окружающие кавычки, чтобы значение можно было сразу передать в буфер обмена или другой команде.
Остальная часть этой статьи посвящена четырём улучшениям, которые превращают эту строку в инструмент, которым действительно удобно пользоваться: shell-функции, корректным кодам выхода, пакетной обработке с ограниченным параллелизмом и буферу обмена. Если вы предпочитаете писать на языке программирования, а не в shell, такой же вызов есть в Python, Go и шести других средах выполнения.
Превратите это в команду
У alias не может быть аргумента, поэтому используйте функцию. В .zshrc или .bashrc:
short() {
[ -z "$1" ] && { echo "usage: short <url> [slug]" >&2; return 2; }
local body
body=$(jq -n --arg url "$1" --arg slug "${2:-}" \
'{destination_url: $url} + (if $slug == "" then {} else {slug: $slug} end)')
curl -s --fail-with-body -X POST https://api.elido.app/v1/links \
-H "Authorization: Bearer $ELIDO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(printf %s "$1" | shasum -a 256 | cut -d' ' -f1)" \
-d "$body" | jq -r .short_url
}
В этой функции есть три осознанных решения.
Построение JSON с помощью jq -n --arg, а не интерполяция строк, означает, что адрес назначения с кавычкой или амперсандом не сломает запрос. Это shell-аналог параметризованного SQL, и пропуск этого шага приводит к тому же классу ошибок.
--fail-with-body - параметр, о котором часто забывают. По умолчанию curl завершается с кодом 0 при любом завершённом обмене, поэтому ответ 401 проходит через конвейер, jq выводит null, а скрипт продолжает работу с null там, где должна быть ссылка. С этим параметром ответ 4xx устанавливает ненулевой код выхода, а тело ошибки по-прежнему можно прочитать.
Idempotency-Key, полученный из URL, означает, что повторный запуск той же команды вернёт ту же ссылку, а не создаст две. Это особенно важно в следующем разделе о пакетной обработке, а объяснение есть в материале о лимитах запросов и идемпотентности.
Нужен ключ? Создайте его на бесплатном тарифе, экспортируйте из профиля shell, и функция заработает в следующем новом терминале.
Сразу в буфер обмена
Последние несколько символов, которые делают решение действительно завершённым:
short "https://example.com/spring-sale" | tee /dev/tty | pbcopy # macOS
short "https://example.com/spring-sale" | tee /dev/tty | xclip -sel c # Linux, X11
short "https://example.com/spring-sale" | tee /dev/tty | wl-copy # Wayland
short "https://example.com/spring-sale" | tee /dev/tty | clip.exe # WSL
tee /dev/tty одновременно выводит ссылку и копирует её, что удобнее, чем копировать вслепую и надеяться на результат.
Пакетная обработка без сбора ответов 429
Файл с URL, по одному в строке, сокращается партиями по восемь адресов:
export -f short # bash; zsh users call the script directly
xargs -P 8 -I{} bash -c 'short "{}"' < urls.txt > short-urls.txt
-P 8 - вся стратегия соблюдения лимита запросов: одновременно выполняются восемь запросов независимо от того, содержит файл пятьдесят строк или пятьдесят тысяч. Без этого параметра xargs запускает процессы настолько быстро, насколько может, и API отвечает 429 на большинство запросов.
Перед применением к настоящему файлу стоит знать о двух нюансах. xargs -P перемешивает вывод, поэтому строки могут прийти не по порядку; если соответствие между входом и выходом важно, выводите оба значения:
xargs -P 8 -I{} bash -c 'printf "%s\t%s\n" "{}" "$(short "{}")"' < urls.txt > mapping.tsv
Кроме того, URL с пробелом или кавычкой не переживёт -I{} без экранирования. Для любых пользовательских данных безопасный вариант - xargs -0 с входным файлом, разделённым нулевыми байтами. На этом этапе написать настоящий скрипт на Python обычно проще, чем правильно настроить кавычки.
Не оставляйте ключ в истории
ELIDO_API_KEY=abc123 short <url> помещает ключ в ~/.zsh_history и список процессов, где его сможет прочитать любой другой аккаунт на компьютере с помощью ps.
Экспортируйте его из профиля shell или, что ещё лучше, получайте из хранилища секретов при запуске shell:
export ELIDO_API_KEY="$(security find-generic-password -s elido -w)" # macOS Keychain
export ELIDO_API_KEY="$(pass show elido/api-key)" # pass
Тогда для ротации ключа достаточно обновить одну запись, а не искать его по скрытым файлам на трёх компьютерах. Тот же принцип действует на серверной стороне любого планируемого скрипта, а webhooks для событий ссылок помогают получать данные обратно, не оставляя ещё один ключ где-то в системе.
Когда терминал подходит лучше всего
Он подходит, когда URL уже находятся в файле, когда вы уже работаете в shell или когда сокращение - один из шагов более крупного скрипта: процесс выпуска, создающий ссылку на дистрибутив, задание CI, сокращающее URL предварительного развёртывания, git hook, который создаёт ссылку для записи в журнале изменений.
Для управления кампанией терминал подходит плохо. Для папок, тегов и сравнения числа кликов по разным размещениям нужна панель, а попытка делать это с помощью запросов jq к endpoint списка превращается в отдельный проект, а не в быстрое решение. В разделе решений для разработчиков описано, что API предоставляет помимо создания ссылок, а API и SDK рассказывают о типизированных клиентах на случай, когда shell-скрипта становится недостаточно.
Читайте основную серию
Эта статья относится к инженерному кластеру. Сначала прочитайте руководство по бесплатному API сокращателя URL, где описан формат endpoint, затем материал о лимитах запросов и идемпотентности. Актуальная справочная информация находится в документации API.
Материалы по теме
Частые вопросы
Как сократить URL из командной строки?
Отправьте адрес назначения в API сокращателя с помощью curl и передайте ответ через jq, чтобы извлечь короткую ссылку. Ничего не нужно устанавливать, кроме curl и jq, а API-ключ берётся из переменной окружения, поэтому он никогда не появляется в истории shell.
Как превратить это в повторно используемую команду?
Оберните вызов curl в shell-функцию в .zshrc или .bashrc, передавая URL первым аргументом. Перезагрузите профиль, и short https://example.com заработает из любого каталога. Здесь функция лучше alias, потому что ей нужно принимать аргумент.
Почему мой конвейер curl завершается успешно, если API вернул 401?
Потому что curl завершается с кодом 0 при любом завершённом HTTP-обмене, включая ответы с ошибками. Добавьте --fail-with-body, чтобы для ответа 4xx или 5xx устанавливался ненулевой код выхода, а тело ответа по-прежнему выводилось. Иначе скрипт продолжит работу с объектом ошибки там, где должна быть короткая ссылка.
Как сократить целый файл URL из shell?
Передайте файл в xargs с параметром -P 8, чтобы одновременно выполнять восемь запросов, и с -I{}, чтобы подставлять каждую строку. Это ограничивает параллелизм восемью запросами независимо от длины файла и не даёт большой пакетной операции выйти за лимит API и собрать ответы 429.
Как сразу скопировать короткую ссылку в буфер обмена?
Передайте вывод в pbcopy в macOS, xclip -selection clipboard в Linux с X11, wl-copy в Wayland или clip.exe в WSL. Вместе с shell-функцией это означает, что одна команда создаёт ссылку, уже готовую для вставки.
Где должен храниться API-ключ для работы из CLI?
В переменной окружения, экспортируемой из профиля shell, или, что ещё лучше, получайте его при запуске shell из менеджера паролей или хранилища секретов. Если вводить ключ прямо в команду, он попадёт в файл истории и список процессов, где его сможет прочитать любой другой пользователь компьютера.
Попробуйте Elido
Вставьте URL - получите короткую ссылку
Без регистрации. Ссылка живёт 30 дней. Зарегистрируйтесь, чтобы оставить её навсегда.
Бесплатно, без регистрации · 2 в день