В своей работе я использую Vim в качестве редактора, а Unix — в качестве «IDE». Я не модифицирую свой vimrc, чтобы добавить в него функции IDE; самый важный плагин, который использую ежедневно — это Ctrl+P, и он нужен мне только для упрощения открытия файлов. Грамотное владение Vim — ценный навык, но важно понимать, когда от него нужно отказаться. В своей повседневной работе я взаимодействую с несколькими терминалами: обычно в одном из них есть Vim, второй используется для запуска сборок или демонов, а в третьем запущен shell, способный выполнить любые мои команды.
Постоянно открытый shell позволяет мне выполнять сложные задачи и отвечать на сложные вопросы. Интересные вещи я нахожу при помощи git grep, масштабные операции поиска и замены я выполняю через sed, отвечаю на вопросы с помощью awk, а более тонкие задачи я выполняю создаваемыми по ходу работы командами и конвейерами shell. Я обладаю свободой творческого решения задач без ограничений, заложенных проектировщиками IDE.
Вот пример задачи, с которой я недавно столкнулся: у меня было множество изменений в репозитории git. Я хотел восстановить удалённые файлы, не теряя другие свои изменения, но их были сотни. Как оптимальнее всего будет решить эту проблему?
Я начал с оценки масштаба проблемы при помощи команды
git status
, которая показала мне сотни удалённых файлов, которые необходимо было восстановить. Понятно, что такие объёмы работы вручную выполнять непрактично, поэтому я ввёл git status -s
, чтобы получить более удобные для конвейера результаты.$ git status -s
D main/a52dec/APKBUILD
D main/a52dec/a52dec-0.7.4-build.patch
D main/a52dec/automake.patch
D main/a52dec/fix-globals-test-x86-pie.patch
D main/aaudit/APKBUILD
D main/aaudit/aaudit
D main/aaudit/aaudit-common.lua
D main/aaudit/aaudit-repo
D main/aaudit/aaudit-server.json
D main/aaudit/aaudit-server.lua
...
С этим уже можно работать. Я добавил
grep '^ D'
, чтобы отфильтровать все строки, которые не были удалены, и пропустил остальные через awk '{ print $2 }'
, чтобы извлечь только имена файлов. Часто я запускаю незавершённый конвейер, чтобы проверить свою работу:$ git status -s | grep '^ D' | awk '{ print $2 }'
main/a52dec/APKBUILD
main/a52dec/a52dec-0.7.4-build.patch
main/a52dec/automake.patch
main/a52dec/fix-globals-test-x86-pie.patch
main/aaudit/APKBUILD
main/aaudit/aaudit
main/aaudit/aaudit-common.lua
main/aaudit/aaudit-repo
main/aaudit/aaudit-server.json
main/aaudit/aaudit-server.lua
...
Очень хорошо — мы создали список файлов, с которыми нужно работать. Стоит заметить, что можно было бы не использовать
grep
и получить тот же результат при помощи одного awk
:$ git status -s | awk '/^ D/ { print $2 }'
main/a52dec/APKBUILD
main/a52dec/a52dec-0.7.4-build.patch
main/a52dec/automake.patch
main/a52dec/fix-globals-test-x86-pie.patch
main/aaudit/APKBUILD
main/aaudit/aaudit
main/aaudit/aaudit-common.lua
main/aaudit/aaudit-repo
main/aaudit/aaudit-server.json
main/aaudit/aaudit-server.lua
...
Однако сейчас мы просто пишем «одноразовую» команду для решения конкретной временной проблемы, поэтому её совершенство для нас не так важно. Никто не будет проверять эту команду. В таких ситуациях я часто решаю по одной проблеме за раз: «отфильтровываем список» и «преобразуем список». Как бы то ни было, последним шагом будет использование этого списка файлов для решения проблемы при помощи команды xargs.
$ git status -s | awk '/^ D/ { print $2 }' | xargs git checkout --
Давайте рассмотрим ещё несколько примеров интересных одноразовых конвейеров shell.
Естественно, для поиска этих примеров я написал конвейер shell:
$ history | cut -d' ' -f2- | awk -F'|' '{ print NF-1 " " $0 }' | sort -n | tail
Что здесь происходит:
history
выводит список истории моих команд shell.cut -d' ' -f2-
удаляет первое поле из каждой строки, используя в качестве разделителя пробел.history
нумерует каждую команду, а эта часть удаляет номер.awk -F'|' '{ print NF-1 " " $0 }
приказывает awk использовать в качестве разделителя полей каждой строки символ | и вывести в качестве префикса каждой строки количество полей. Эта команда выводит каждую строку из моей истории с префиксом — количеством вхождений оператора конвейера в этой строке.sort -n
сортирует этот список численно.tail
выводит последние 10 элементов.
Эта команда, написанная за считанные секунды, находит, характеризует, фильтрует и сортирует мою историю shell по сложности команд. Вот пара крутых команд shell, которые мне удалось найти:
Воспроизведение 50 самых новых видео в папке при помощи mpv:
ls -tc | head -n50 | tr '\n' '\0' | xargs -0 mpv
Я постоянно использую эту команду. Если я хочу посмотреть видео позже, то использую для этого файла touch, чтобы он отображался в начале этого списка. Ещё одна команда передаёт при помощи
netcat
tarball пропатченной версии Celeste моему другу, за исключением (больших) ресурсов игры. Процесс передачи отображается при помощи pv:find . ! -path './Content/*' | xargs tar -cv | pv | zstd | nc 204:fbf5:... 12345
А вот, что происходит на стороне моего друга:
nc -vll :: 12345 | zstdcat | pv | tar -xv
Кстати, tar — это недооценённый инструмент для перемещения групп файлов по конвейеру. Он может считывать и записывать tarball в stdin и stdout!
Надеюсь, эта статья дала вам представление о мощи Unix shell. Если вы хотите больше узнать о командной оболочке, то рекомендую shellhaters.org в качестве введения в различные части спецификации POSIX, связанные с shell. Не бойтесь спецификации — это краткий, исчерпывающий и понятный текст, в котором полно примеров. Ещё я крайне рекомендую уделить время изучению конкретно awk: вот краткий туториал.
На правах рекламы
Серверы для разработчиков и не только! Аренда виртуального сервера на базе новейших процессоров AMD и Intel, хранилище на основе NVMe дисков для размещения проектов любой сложности, создавайте собственную конфигурацию сервера в пару кликов!
Подписывайтесь на наш чат в Telegram.
tonad
И снова переносим свой частный уникальный опыт на всех программистов..
artem_larin
Ну про чужой опыт крайне интересно почитать.
DrPass
Тем не менее, хотелось бы объективности. Например, вместо «Грамотное владение shell — один из самых важных навыков, которыми вы как программист должны обладать» начать статью с «shell — мощный инструмент, владение которым, может быть, вам поможет повысить свою продуктивность». Я, например, первую свою коммерческую программу написал в 1999-м году, с тех пор писал под всё, что только можно придумать, от IBM AS/400 до микроконтроллеров. Но блин, у меня ни разу в жизни не было задач, которые можно было быстрее решить, написав одноразовый скрипт на шелле, нежели воспользоваться готовыми тулзами IDE плюс, где надо, руками что-то подправить через файловый менеджер.
codelock
Кажется, что это Вас задело и Вы пытаетесь перевести с больной головы на здоровую.
По крайней мере, для меня это выглядит очень странно, потому что, если Вы не понимаете зачем Вам, как программисту, гибкий инструмент автоматизации, то я уж и не знаю зачем вообще заниматься программированием.
mayorovp
У меня, как у программиста, уже есть гибкий инструмент автоматизации — тот язык на котором я пишу.
codelock
Не знаю на чём Вы пишите, но я применяю разные инструменты для разных задач
Kanut
И все эти задачи требуют использования shell'a? И если нет, то вам так трудно представить себе что у других людей все задачи не требуют использования shell'a или как минимум спокойно решаются без его использования?
codelock
Многие задачи и так решаются без использования компьютера. Вам так сложно представить, что у других людей все задачи решаются без его использования?
Kanut
Нет не сложно. Поэтому я и не утверждаю что "для людей всех профессий компьютер так же необходим, как умение читать" или ещё что-то в этом роде.
Если вам для работы необходим shell, то это ваше дело и ничего плохого в этом нет. Но это не значит что он необходим абсолютно всем айтишникам без исключения.
codelock
Вероятно, я не смог донести суть, но имел ввиду, что задачи могут решатся разными способами, но какой смысл использовать компьютер, если решать их неэффективно
Kanut
С чего вы решили что все программисты не могут решать свои задачи эффективно не используя shell?
Я сомневаюсь например что использование shell сделает особо эффективнее человека, который пишет десктоп-приложения на том же WPF'e.
DrPass
Хм. Человек, который зарегистрировался, только чтобы ответить на мой комментарий, говорит, что меня это задело :)
Объясняю: программируя, я решаю какие-то конкретные задачи. Для каждой задачи есть какие-то свои инструменты. Некоторые оптимальные, некоторые не очень. Некоторые универсальные, некоторые специализированные. И у меня есть удобные мне, и я бы сказал, оптимальные инструменты для всех моих задач.
И, соответственно, мне не нужен гибкий инструмент автоматизации, если 99% этих задач и так давно автоматизированы в IDE, а оставшийся 1% встречается в практике раз в несколько лет, и автоматизация их скриптами шелла никогда в жизни не окупит время, потраченное на чтение манов и потом на собственно написание скриптов. Тем более, что я всё это могу сделать, просто набросав утилитку непосредственно на языке программирования.
И я не ошибусь, если скажу, что у подавляющего большинства программистов ситуация такая же, как и у меня: нет там никаких задач, которые нужно дополнительно автоматизировать за пределами IDE. А просто так изучать инструмент, потому что он прикольный? Ну, у всех разные хобби бывают. Я предпочитаю это время потратить в своей мастерской, например. Там я сделаю что-то куда более интересное для меня, чем изучить командный язык очередной софтины, которой мне не придётся пользоваться.
codelock
Интересно Вы интерпретируете данные, если дата регистрации указана - 16 июня
saboteur_kiev
Основная задача таких вещей как shell или powershell или bat — это автоматизация задач на енвайрнментах, а не в IDE. И в небольших проектах, где не нужен свой сисдамин и команда, которая поддерживает инфраструктуру, это падает на разработчика. Или вы прямо из IDE деплоите в продакшен?
DrPass
Вы так говорите, будто бы в этом что-то плохое :) Если проект настолько небольшой, что там нет ни девопса, ни даже админа, а деплоем занимается непосредственно разработчик, то почему бы не из IDE? Прогнал тесты, переключил в IDE профиль деплоя с теста на прод — и отправил.
И опять же таки, для того, чтобы запустить сборку и потом отправить файлы, знать shell не нужно. Это можно успешно сделать, даже увидев его первый раз в жизни, и не читая манов.
Kanut
Ну как бы для того чтобы деплоить тоже есть свои IDE и UI. И это совсем не обязательно делать через shell. Тот же Visual Stuido вполне себе имеет достаточно функциональности чтобы "простой разработчик" мог более менее комфортно работать с майкрософтофским TFS и не заморачиваться shell'ом. И вроде бы обещают добавить такую же функциональность и для гита.
То есть для админа/девопса этого однозначно мало. Если ты просто коммитишь, делаешь ревью и деплоишь, то хватает за глаза и за уши.