3 трюка для терминала, о которых вам хотелось бы знать раньше
Неважно, учитесь ли вы работать с терминалом или уже опытный пользователь, всегда есть множество маленьких трюков, которые вы можете выучить — трюков, которые экономят ваше время. У меня есть три полезных трюка Bash, которые вы можете добавить в свой арсенал.
Подстановка процессов для преобразования данных во временные файлы данных
Возможно, вы сталкивались с ситуацией, когда вам нужен был путь к файлу в качестве аргумента, а у вас были только данные.
Например, допустим, вы хотите отредактировать текст, который уже есть в терминале:
echo "foo" | nano
Предыдущая команда не работает, потому что нельзя передавать данные в nano через конвейер; вместо этого нужно указать путь к файлу, например: nano /path/to/file.txt.
Чтобы решить эту проблему, вы, вероятно, будете использовать последовательность команд, подобную следующей:
echo foo > bar.txt nano bar.txt
С помощью двух отдельных команд вы создаёте файл, а затем что-то с ним делаете. Такой подход является неоптимальным, потому что файлы остаются разбросанными по вашей файловой системе, и вам также приходится вводить путь к ним. Подстановка процессов решает эту проблему:
echo <(true)
Если бы вы выполнили предыдущую команду, вы бы увидели, что она выводит путь к файлу, подобный следующему:
/dev/fd/16
Подстановка процесса создает временный файл из вывода команды, позволяя другой команде читать из него. Таким образом, в предыдущем примере «<(true)» генерирует путь к выводу, а «echo» его получает. Данные в выводе просто равны «true».
Часть пути «fd» относится к термину «дескриптор файла», который просто является идентификатором, используемым программным обеспечением для внутреннего обращения к открытым файлам. В этом примере дескриптор файла имеет значение 16. Дескрипторы файлов являются приватными для процессов, которые их используют — в данном случае это «echo».
Давайте используем подстановку процесса полезным образом:
nano <(echo "foo")
Предыдущая команда эквивалентна введению следующей:
echo "foo" > /tmp/foo nano /tmp/foo
Вы не сможете сохранять и редактировать текст при запуске nano <(echo "foo"), потому что специально созданный файл доступен только для чтения, но вы можете изменить место его сохранения с помощью сочетания клавиш Ctrl+o.
Подстановка процесса ввода/вывода
Выражение "<(foo)" создаёт подстановку процесса для ввода. В качестве альтернативы, вы также можете создать подстановку процесса для вывода:
echo "foo" > >(cat)
Предыдущая команда эквивалентна введению следующей:
echo "foo" > /tmp/foo cat /tmp/foo
Хотя эти две команды могут казаться разными, они работают одинаково. Это становится яснее, когда вы понимаете, что echo "foo" > >(cat) записывает "foo" в специальный файл, из которого затем читает команда cat.
Итак, подводя итог:
- echo <(true) — это подстановка процесса ввода, и echo получает данные через специальный путь к файлу (в данном случае данные — только «true»).
- echo "foo" > >(cat) является выходной подстановкой процесса, и cat получает выведенное слово через специальный путь. Первый символ ">" — это оператор перенаправления, а второй является частью самой подстановки.
Чтобы завершить этот раздел, я думаю, что реальный пример удачно всё свяжет:
diff <(ls -1 ~) <(ls -1 /tmp)
Эта команда сравнит различия между двумя директориями. Использование подстановки процесса во входных данных полезно в этом случае, потому что diff ожидает пути к файлам, а именно это и предоставляет подстановка процесса.
Флаг «ls -1» — это единица, а не буква l.
Расширение истории для повторения команд
Разработчики Bash часто используют термин «расширение». Это звучит сложно, но на самом деле просто означает преобразование чего-то маленького во что-то большее — расширение. Самый известный пример — расширение тильды (~), которое заменяется на путь к вашему домашнему каталогу.
Следующие три примера называются расширениями истории. Эти выражения расширяются от простых вводимых символов до элементов вашей истории команд оболочки.
Бах, бах!!
Это одна из команд, которой я пользуюсь чаще всего после cd и ls. Ею просто пользоваться и её легко понять. Она повторно выполняет последнюю вашу команду.
ls !!
Вы можете видеть из вывода команды, что команда ls выполняется дважды.
Развернуть конкретный элемент в вашей истории
Сначала просмотрите вашу историю, чтобы выбрать подходящую команду:
history
Затем просто выберите один из чисел слева и вставьте его в качестве N:
!N
Дважды проверьте команду перед её повторным выполнением, потому что если вы случайно выполните неправильную команду, ваш день будет испорчен.
Лучшее в том, что при раскрытии этих пронумерованных элементов истории их номера остаются неизменными, заключается в том, что это позволяет вам с ними знакомиться. Конечно, это знакомство длится только до тех пор, пока вы не удалите файл ~/.bash_history.
Развернуть по имени для более удобного выбора
Частый поиск в истории команд и нахождение определённой команды по её номеру может быть утомительным. Существует альтернативный и более эффективный способ: Bash позволяет частично набрать начало команды, и будет выполнено самое последнее совпадение.
echo foo !e !ech
Это идеально, когда нужно чередовать несколько команд в одной сессии терминала. Однако для более старых команд я предпочитаю использовать инструмент для нечеткого поиска в истории.
Группы команд
Иногда вы захотите выполнить несколько команд как группу, но воспринимать их вывод как один результат. Рассмотрим следующий пример:
echo foo > /tmp/foo.txt echo bar >> /tmp/foo.txt
Символ «>» называется оператором перенаправления и отправляет вывод команды в указанный файл, перезаписывая его содержимое; «>>» делает то же самое, за исключением того, что добавляет данные в файл — то есть оператор перенаправления для добавления (append).
Предыдущая команда создаст файл, который будет выглядеть следующим образом:
foo bar
Иногда, когда ваши команды более сложные, использование такого подхода может выглядеть некрасиво из-за большого количества ненужных строк. Более простой подход — использовать группу команд.
Группа команд объединяет все выходные данные своих команд в один. Это делает обработку результата значительно проще.
{ echo foo; echo bar; } > /tmp/foo.txt
Это приведет к такому же результату, как и предыдущая команда. Перенаправление должно происходить только один раз, поэтому оператор добавления перенаправления (>>) не нужен.
После каждой команды требуется точка с запятой, особенно после последней команды. Также необходимы пробелы между скобками и словами команд.
Вы можете доказать, что команды вне группы выполняются только один раз, выполнив следующую последовательность команд:
{ echo "A"; echo "B"; } | wc -l
Группа команд отправляет оба вывода echo вместе как единый поток. Вот почему «wc» считает обе строки вместе как одно сообщение и показывает 2; в противном случае он показал бы 1 на двух отдельных строках.
Пример реального сценария использования:
{ ping -c 1 example.com; ping -c 1 example.net; } > /tmp/ping.txt
Вкратце:
- Подстановка процесса заменяет процесс временным файловым путем. Например, nano <(echo "foo") и echo "foo" > >(cat).
- Расширения истории Bash — это специальные символы, которые ссылаются на элементы вашей истории Bash. Например, !foo, !N или !!.
- Группа команд объединяет вывод нескольких команд в один результат. Например, { echo "foo"; echo "bar"; } > /tmp/foo.txt.
Все, что рассмотрено, лишь поверхностно охватывает возможности Bash. Если вас привлекают расширения истории оболочки, вам понравится наш учебник о том, как использовать команду history. Вас также могут заинтересовать советы, которые облегчают изучение командной строки.




Добавить комментарий