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

Несколько дней назад я написал статью о своем опыте работы с Vim.



Хотя я в основном сосредоточился на текстовых редакторах и процессе написания кода, есть еще одна важная тема, о которой я там не говорил — зависимость от терминала.

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

Как только я начал использовать Vim, я, естественно, стал более привязан к своему терминалу. Это заставило меня понять, как много я упускаю. Сегодня я собираюсь показать вам замечательные вещи, которые вы можете сделать с помощью своего терминала.

Пугающая сила раковины

Оболочка — это мост между вами и ядром. Тяжело, я понимаю. Для неподготовленного глаза действительно грязно работать на таких экранах:

И как я должен перемещаться по своим файлам таким образом?

Я думаю, что у всех возникают одни и те же мысли, когда они знакомятся с такой оболочкой. Многие из этих инструментов существовали на заре программирования — они не были точно разработаны с учетом UX (или, лучше сказать, DX?). Несмотря на проблемы с внешним видом, это единственный способ использовать вашу систему в полной мере.

Это не должно быть уродливым

Скриншоты, которые я показывал вам ранее, не являются тем, что я использую в своем рабочем процессе. Терминал — это ваш холст, и как только вы изучите свои инструменты, вы сможете настроить или заменить их так, как вам хочется.

Так что да, есть некоторые инструменты командной строки, которые я использую просто для вида. В моих конфигурациях ZSH ls — это псевдоним для exa, который является современной заменой ls — как описано в файле README Exa.

Вы можете видеть, что я использовал команду lh, но на самом деле это псевдоним для следующего:

exa --icons -lha

То же самое касается и управления процессами — top является инструментом по умолчанию — его нет и в моей цепочке инструментов. Для этой цели я использую htop.

Есть и другие альтернативы, но я действительно склоняюсь к любвиbottom, которая позволяет мне все время открывать ее в сеансе Tmux:

Если вам не нравится, как что-то выглядит, я уверен, вы найдете то, что подходит именно вашим глазам. Я даже не говорил о самой подсказке — которую я использую Звездолет.

Теперь начинается удивительная часть

Конечно, мы получили красивый интерфейс командной строки. Что теперь? Где вся сила, которую я рекламировал для вас? Не ждите больше! Давайте перейдем к некоторым примерам, чтобы вы могли получить представление.

Поиск материалов

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

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

Bash имеет эту команду под названием grep, которая существует именно для этой цели. Представьте, что вам нужно отредактировать файл ZSH, но вы не можете вспомнить его имя. Не беспокойтесь больше! Мы можем перечислить все наши файлы и направить (|) вывод в grep.

Разобьем на части:

  • Мы перечисляем все файлы и каталоги, которые у нас есть, используя lh;
  • | получит вывод команды слева и перейдет на стандартный ввод к команде справа.
  • grep будет искать термин «zsh», содержание его поиска исходит от lh.

Включите на мгновение свое воображение, представьте, как много вы можете сделать с помощью этого синтаксиса.

У меня есть проект прототипа игры с большим количеством коммитов. Допустим, я хочу выбрать коммиты, которые я сделал, связанные с вводом данных игроком. grep спешит на помощь!

Мы можем пойти еще дальше и установить еще один инструмент командной строки под названием FZF. fzf — это нечеткий поиск командной строки общего назначения. Кроме того, он невероятно быстр как они заявляют.

Красиво, правда?

Кроме того, помните, я сказал, что вы можете заменить все, что захотите? Мастер BurntSushi придумал новую реализацию Grep, которая обещает быть в целом быстрее, чем Grep.



Мы могли бы использовать его вместо классического Grep для той же цели. Давайте выполним тот же поиск, что и ранее, используя Grep и Ripgrep, чтобы увидеть визуальные различия:

Обратите внимание, как хорошо Ripgrep — команда rg — выделяет соответствующий термин в сообщении, что очень удобно, когда у нас есть стены текста, извлеченные инструментом.

Поскольку у меня всего несколько коммитов в этом репозитории, улучшение скорости было минимальным. Однако это действительно сияет при выполнении рекурсивного поиска.

Передача дополнительных команд

Мы можем сделать еще один шаг вперед с этим последним примером. Предположим, мне нужно отменить определенный коммит, который мне сначала нужно найти. Мы также можем накачать их. На самом деле, мы можем передать столько команд, сколько захотим!

Хорошо, это немного сложнее, чем то, что я показывал до этого момента, поэтому давайте также разберем его:

  • git log --oneline — перечисляет все коммиты в формате одной строки;
  • fzf — Механизм Fuzzy-finder, о котором мы говорили ранее;
  • xargs -n 1 git revert — Команда, которую мы хотим выполнить. Мы говорим Xargs принимать по одному аргументу за раз.

Последнее может немного сбить с толку, поэтому я написал целую статью о Xargs. Если вы не совсем понимаете эту командную утилиту, я настоятельно рекомендую проверить ее!



В конце концов, Git не смог отменить нашу фиксацию из-за конфликтов, которые нам нужно было разрешить. Теперь мы находимся в этом состоянии REVERTING.

Управление файлами

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

Поверьте, я был там. Достаточно использовать только оболочку.

Операции с файлами существуют задолго до того, как это делают удобные оконные файловые менеджеры. cp для копирования и вставки файлов. mv, чтобы переместить их. Скажем, у вас есть каталог, и вы хотите скопировать некоторые файлы. Достаточно просто!

cp foo/file1.txt bar/

Таким образом мы скопировали file1.txt в каталог bar/. Мы даже можем перемещать несколько файлов одновременно.

cp foo/file1.txt foo/file2.txt foo/image.jpg bar/

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

Использование mv позволяет нам даже переименовывать файлы.

mv foo/file1.txt foo/descriptive-name.txt

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

mv foo/* bar/

Если bar/ не существует, почему бы тогда просто не переименовать foo/?

mv foo/ bar/

Снова пришло время для более сложного действия. Допустим, мы хотим переместить все файлы в bar/, кроме тех, в имени которых есть «ba».

Мы пойдем с Ripgrep для этого, это просто лучше! Но на самом деле мы будем использовать -v для инвертирования шаблона. Это означает, что если файл содержит указанный нами шаблон, он будет исключен из вывода.

И, поскольку у меня есть значки, настроенные на псевдоним ls, я буду использовать exa только для того, чтобы эти значки не мешали командам.

cd foo
exa | rg -v 'ba' | xargs -I{} mv {} ../bar

Сначала мы cd заходим в каталог, чтобы иметь возможность тесно работать с этими файлами. Ripgrep позаботится об фильтрации этих файлов. Xargs будет выполнять mv {} ../bar для каждого выходного файла, являясь {} местом, где будут располагаться аргументы.

Навигация с Zoxide

Мы все знаем cd. Это способ по умолчанию изменить текущий каталог. Я хочу показать вам лучшее cd.



Как следует из описания: zoxid — более умная команда cd. Он делает это, сохраняя ваши наиболее часто используемые файлы и позволяя вам переходить через использование ключевых слов.

Я буду использовать свой собственный пример. У меня есть папка, расположенная ~/projects/games/duel_prototype. Он не супервложенный, как другие папки, но нужно приложить усилия, чтобы все это напечатать. После установки Zoxid я буду перемещаться так же, как с cd, но мы будем использовать команду z.

z ~/projects/games/duel_prototype

Большое дело приходит, когда мы пытаемся получить доступ к этому пути позже. На этот раз мы можем ввести имя папки, в которую хотим перейти, но частично. Все приведенные ниже команды будут управлять одним и тем же:

z duel_prototype

z duel

z games duel

z duel prototype

z due

Я могу просто ввести имя папки, частичное имя, небольшие части пути, чтобы добраться туда… Возможности огромны. Он использует нечеткий поиск под капотом, объясняя гибкость.

Для моего личного ноутбука это не так уж много. Но на моей работе у меня есть разные папки для постоянных клиентов, новых клиентов, внутренних инструментов и приложений с открытым исходным кодом VTEX. Набирать весь путь неудобно, и даже имя иногда мне непонятно.

С Zoxide, если я возился с одним проектом в ~/really/nested/project/ и хочу вернуться к ~/also/very/nested/big-project/, это так же просто, как сделать это:

z big project

Примеры из жизни

Сравнение файлов

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

Я не буду делиться подробностями по этому вопросу, но давайте продолжим этот брифинг:

Сайт клиента столкнулся с неожиданным поведением. Мы подумали, что, возможно, это решит обновление зависимостей. Однако мы боялись, что это может привести к еще большим проблемам.

Вывести список зависимостей с помощью CLI легко, просто выполните vtex ls. Обновление также довольно простое, vtex upgrade и готово.

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

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

Во-первых, мы сохранили текущее состояние vtex ls.

vtex ls > old.txt

Это перенаправляет вывод команды слева (vtex ls) на путь к файлу справа (old.txt).

Пришло время обновить эти зависимости!

vtex upgrade

По окончании снова сохраним текущие версии, но уже в другой файл с указанием нового состояния.

vtex ls > new.txt

Имея old.txt и new.txt на своих местах, мы можем легко использовать команду diff, чтобы увидеть, что изменилось между ними. Чтобы сделать все еще лучше, мы можем передать --colors, чтобы сделать все более читабельным.

Теперь мы точно знаем, какие зависимости получили обновление. Если что-то пойдет не так, они будут первыми подозреваемыми!

В этой ситуации большинство людей поступило бы — при условии, что у них есть файлы с одинаковыми метками — погуглили бы Сравнить различия между файлами в Интернете» и нашли бы веб-сайт, который делает то же самое.

Это немного натянуто. Зачем идти на случайный веб-сайт, заполненный рекламой, когда у вас есть объединенный инструмент прямо в вашей надежной оболочке?

Надежное отслеживание версий

Мне очень нравится этот пример, потому что он показывает, как очень простые сценарии могут сделать вашу жизнь намного проще.

В этом проекте командной строки компании я должен был создать очень простую команду version, которую большинство инструментов должно отображать в текущей версии. Проблема в том, что с этого момента мне придется обновлять номер версии как в файле package.json, так и в файле index.ts, где задается команда.

Чтобы решить эту проблему, я сделал простой скрипт, который будет генерировать эту константу LIB_VERSION, которая извлекает актуальную версию из файла package.json и записывает ее в файл src/constants/version.ts.

node -p "'export const LIB_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'" > src/constants/version.ts

Чтобы автоматизировать это, я просто связал это со скриптом build. Использование синтаксиса && приведет к остановке выполнения сборки в случае сбоя prebuild.sh.

{
  // ... stuff
  "scripts": {
    // other scripts
    "build": "./prebuild.sh && tsc"
  }
}

Благодаря этому мне больше никогда не приходилось беспокоиться об актуальной версии. Файл version.ts игнорируется Git, так что мне не о чем беспокоиться.

Последние мысли

Часто работа программиста будет заключаться в создании решений. Для этого вам обязательно потребуется некоторое время, чтобы понять один инструмент, который всегда находится прямо на вашем компьютере: оболочку.

Это может занять некоторое время, чтобы привыкнуть к этому, и я планирую написать больше статей на эту тему, так как я очень люблю эту тему.

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

Спасибо, что прочитали мою статью, надеюсь видеть вас здесь чаще!