Обзор курса + введение в командную оболочку
Кто мы?
Этот курс совместно ведут Аниш, Джон и Хосе. Мы все бывшие студенты MIT и запустили этот курс в рамках MIT IAP ещё в те времена, когда сами были студентами. Написать нам всем сразу можно по адресу missing-semester@mit.edu.
Нам не платят за преподавание этого курса, и мы никак не монетизируем его. Все материалы курса и записи лекций мы свободно выкладываем в интернет. Если хотите поддержать нашу работу, лучший способ – просто рассказывать о курсе другим. Если вы компания, университет или другая организация, которая прогоняет эти материалы через большие группы слушателей, пришлите нам, пожалуйста, отчёты об опыте или отзывы по электронной почте – нам будет приятно об этом узнать :)
Мотивация
Как специалисты по информатике, мы знаем, что компьютеры отлично справляются с помощью в повторяющихся задачах. Однако слишком часто мы забываем, что это относится к нашему использованию компьютера ничуть не меньше, чем к вычислениям, которые мы поручаем своим программам. У нас под рукой огромный набор инструментов, которые позволяют работать продуктивнее и решать более сложные проблемы при работе над любой задачей, связанной с компьютером. И всё же многие из нас пользуются лишь малой долей этих инструментов; мы знаем наизусть ровно столько магических заклинаний, сколько нужно, чтобы кое-как обходиться, и слепо копируем команды из интернета, когда застреваем.
Этот курс – попытка исправить это.
Мы хотим научить вас выжимать максимум из уже знакомых инструментов, показать новые инструменты, которые стоит добавить в свой арсенал, и, надеемся, заразить вас интересом к самостоятельному изучению (а может, и созданию) новых инструментов. Именно это мы считаем тем самым пропущенным семестром большинства учебных программ по Computer Science.
Структура курса
Курс не идёт в зачёт и состоит из девяти часовых лекций, каждая из которых посвящена отдельной теме. Лекции в основном независимы друг от друга, хотя по ходу семестра мы будем предполагать, что вы знакомы с содержанием предыдущих лекций. Конспекты лекций выложены онлайн, но что-то из разобранного на занятиях (например, демонстрации) в конспекты может не попасть. Как и в прошлые годы, мы будем записывать лекции и выкладывать записи онлайн.
Мы пытаемся охватить очень многое всего за несколько часовых лекций,
поэтому лекции довольно насыщенные. Чтобы вы могли освоить материал в
своём темпе, к каждой лекции прилагается набор упражнений, которые
проводят вас по её ключевым моментам. Отдельных консультаций мы проводить
не будем, но приглашаем задавать вопросы в
Discord OSSU, в канале
#missing-semester-forum или писать нам на
missing-semester@mit.edu.
Из-за ограниченного времени мы не сможем разобрать все инструменты так подробно, как это сделал бы полноценный курс. Где возможно, мы постараемся указать вам ресурсы, чтобы копнуть глубже в инструмент или тему, но если что-то вас особенно зацепит – не стесняйтесь написать нам и попросить подсказок!
Наконец, если у вас есть отзывы о курсе, пожалуйста, присылайте их нам по электронной почте на missing-semester@mit.edu.
Тема 1: Командная оболочка
Что такое командная оболочка?
У современных компьютеров есть множество интерфейсов, через которые им можно отдавать команды: затейливые графические интерфейсы, голосовые интерфейсы, AR/VR, а с недавних пор – LLM. Для 80% задач они отлично подходят, но зачастую принципиально ограничены в том, что позволяют делать: нельзя нажать кнопку, которой нет, или отдать голосовую команду, которую никто не запрограммировал. Чтобы по-настоящему воспользоваться всеми инструментами, которые предоставляет компьютер, придётся действовать по старинке и спуститься к текстовому интерфейсу – командной оболочке (shell).
Почти на любой платформе, которая попадёт вам в руки, есть оболочка в том или ином виде, а на многих – сразу несколько на выбор. Они могут различаться в деталях, но по сути все примерно одинаковы: они позволяют запускать программы, передавать им ввод и изучать их вывод в полуструктурированном виде.
Чтобы открыть приглашение командной строки (куда можно вводить команды), сначала нужен терминал – визуальный интерфейс к оболочке. Скорее всего, он уже был установлен на вашем устройстве, либо его довольно легко установить:
- Linux:
Нажмите
Ctrl + Alt + T(работает в большинстве дистрибутивов). Или найдите «Terminal» в меню приложений. - Windows:
Нажмите
Win + R, введитеcmdилиpowershellи нажмите Enter. Либо найдите «Terminal» или «Command Prompt» в меню «Пуск». - macOS:
Нажмите
Cmd + Space, чтобы открыть Spotlight, введите «Terminal» и нажмите Enter. Или найдите его в Applications → Utilities → Terminal.
На Linux и macOS при этом обычно открывается Bourne Again SHell, или сокращённо «bash». Это одна из самых распространённых оболочек, и её синтаксис похож на то, что вы увидите во многих других оболочках. На Windows вас встретит оболочка «batch» или «powershell» – в зависимости от того, какую команду вы запустили. Они специфичны для Windows, и в этом курсе мы не будем на них сосредотачиваться, хотя у них есть аналоги почти всего, о чём мы будем рассказывать. Вместо этого вам понадобится Windows Subsystem for Linux или виртуальная машина с Linux.
Существуют и другие оболочки, зачастую с множеством эргономических улучшений по сравнению с bash (fish и zsh – среди самых распространённых). Хотя они очень популярны (все преподаватели пользуются одной из них), им далеко до повсеместности bash, и опираются они во многом на те же концепции, поэтому в этой лекции мы не будем на них останавливаться.
Почему это должно вас волновать?
Оболочка не просто (как правило) гораздо быстрее, чем «тыкать мышкой», – она обладает выразительной мощью, которую нелегко найти ни в одной отдельно взятой графической программе. Как мы увидим, оболочка даёт возможность комбинировать программы самыми изобретательными способами и автоматизировать почти любую задачу.
Умение ориентироваться в оболочке очень пригодится и в мире открытого программного обеспечения (инструкции по установке там часто требуют оболочки), и при настройке непрерывной интеграции для ваших проектов (об этом рассказывается в лекции «Качество кода»), и при отладке ошибок, когда другие программы отказываются работать.
Навигация в оболочке
Когда вы запустите терминал, вы увидите приглашение командной строки, которое обычно выглядит примерно так:
missing:~$
Это основной текстовый интерфейс оболочки. Он сообщает вам, что вы
находитесь на машине missing и что ваш «текущий рабочий каталог», то
есть место, где вы сейчас находитесь, – это ~ (сокращение от «home»,
домашний каталог). Знак $ говорит о том, что вы не пользователь root
(об этом позже). В это приглашение можно ввести команду, которую затем
интерпретирует оболочка. Самая простая команда – запустить программу:
missing:~$ date
Fri 10 Jan 2020 11:49:31 AM EST
missing:~$
Здесь мы запустили программу date, которая (что, пожалуй, неудивительно)
печатает текущие дату и время. Затем оболочка просит у нас следующую
команду для выполнения. Мы также можем выполнить команду с аргументами:
missing:~$ echo hello
hello
В этом случае мы велели оболочке запустить программу echo с аргументом
hello. Программа echo просто печатает свои аргументы. Оболочка
разбирает команду, разбивая её по пробелам, а затем запускает программу,
указанную первым словом, и передаёт каждое последующее слово как
аргумент, к которому программа может обратиться. Если нужно передать
аргумент, содержащий пробелы или другие специальные символы (например,
каталог с именем «My Photos»), можно либо заключить аргумент в кавычки
' или " ("My Photos"), либо экранировать только нужные символы с
помощью \ (My\ Photos).
Пожалуй, самая важная команда, когда вы только начинаете, – это man,
сокращение от «manual» (руководство). Программа man, помимо прочего,
позволяет посмотреть подробную информацию о любой команде в вашей
системе. Например, если запустить man date, она объяснит, что такое
date и какие аргументы можно ей передать, чтобы изменить её поведение.
Кроме того, у большинства команд можно получить краткую справку, передав
им аргумент --help.
Подумайте о том, чтобы установить и использовать
tldrв дополнение кman: она показывает типичные примеры использования прямо в терминале. LLM тоже, как правило, отлично объясняют, как работают команды и как их вызывать, чтобы добиться желаемого.
После man самая важная команда, которую стоит выучить, – это cd, или
«change directory» (сменить каталог). На самом деле эта команда встроена
в оболочку и не является отдельной программой (то есть which cd скажет
«no cd found»). Вы передаёте ей путь, и этот путь становится вашим
текущим рабочим каталогом. Рабочий каталог также отображается в
приглашении командной строки:
missing:~$ cd /bin
missing:/bin$ cd /
missing:/$ cd ~
missing:~$
Обратите внимание, что в оболочке есть автодополнение, так что пути зачастую можно быстрее дописать, нажав
<TAB>!
Многие команды работают с текущим рабочим каталогом, если не указано
иное. Если вы вдруг не уверены, где находитесь, можно запустить pwd
или напечатать переменную окружения $PWD (командой echo $PWD) – и
то и другое выведет текущий рабочий каталог.
Текущий рабочий каталог удобен ещё и тем, что позволяет использовать
относительные пути. Все пути, которые мы видели до сих пор, были
абсолютными – они начинаются с / и задают полный набор каталогов,
через которые нужно пройти от корня файловой системы (/), чтобы
добраться до нужного места. На практике вы чаще будете работать с
относительными путями; они так называются, потому что отсчитываются
относительно текущего рабочего каталога. В относительном пути (любом,
который не начинается с /) первый компонент ищется в текущем рабочем
каталоге, а последующие компоненты обходятся как обычно. Например:
missing:~$ cd /
missing:/$ cd bin
missing:/bin$
Есть также два «особых» компонента, которые существуют в каждом
каталоге: . и ... . – это «этот каталог», а .. – «родительский
каталог». Так что:
missing:~$ cd /
missing:/$ cd bin/../bin/../bin/././../bin/..
missing:/$
Обычно абсолютные и относительные пути можно использовать взаимозаменяемо в качестве аргумента любой команды – просто помните, какой у вас текущий рабочий каталог, когда используете относительный!
Подумайте о том, чтобы установить и использовать
zoxide, чтобы ускорить своиcd–zзапоминает пути, которые вы часто посещаете, и позволяет переходить к ним, набирая меньше символов.
Что доступно в оболочке?
Но откуда оболочка знает, где искать программы вроде date или echo?
Когда оболочку просят выполнить команду, она обращается к переменной
окружения $PATH, в которой перечислены каталоги, где оболочка должна
искать программы, когда ей дают команду:
missing:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
missing:~$ which echo
/bin/echo
missing:~$ /bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Когда мы запускаем команду echo, оболочка видит, что должна выполнить
программу echo, и затем ищет файл с таким именем в списке каталогов из
$PATH, разделённых :. Найдя его, она его запускает (при условии, что
файл исполняемый; об этом позже). Узнать, какой именно файл выполняется
для данного имени программы, можно с помощью программы which. Мы также
можем полностью обойти $PATH, указав путь к файлу, который хотим
выполнить.
Это же подсказывает, как определить все программы, которые мы можем
выполнить в оболочке: перечислить содержимое всех каталогов из $PATH.
Для этого можно передать путь к нужному каталогу программе ls, которая
выводит список файлов:
missing:~$ ls /bin
Подумайте о том, чтобы установить и использовать
eza– более дружелюбную к человеку версиюls.
На большинстве компьютеров это выведет очень много программ, но здесь мы сосредоточимся лишь на некоторых самых важных. Сначала – несколько простых:
cat fileвыводит содержимое файлаfile.sort fileвыводит строки файлаfileв отсортированном порядке.uniq fileубирает изfileидущие подряд повторяющиеся строки.head fileиtail fileвыводят соответственно первые и последние несколько строк файлаfile.
Подумайте о том, чтобы установить и использовать
batвместоcat– ради подсветки синтаксиса и прокрутки.
Есть ещё grep pattern file, которая находит в file строки,
соответствующие pattern. Она заслуживает чуть большего внимания: она
очень полезна и умеет куда больше, чем можно ожидать. На самом деле
pattern – это регулярное выражение, которым можно описывать очень
сложные шаблоны – мы разберём
их
в лекции о качестве кода. Вместо файла можно также указать каталог (или
вовсе опустить его, тогда подразумевается .) и передать -r, чтобы
рекурсивно искать по всем файлам в каталоге.
Подумайте о том, чтобы установить и использовать
ripgrepвместоgrep– это более быстрая и дружелюбная к человеку (но менее переносимая) альтернатива. К тому жеripgrepпо умолчанию рекурсивно ищет по текущему рабочему каталогу!
Есть и несколько очень полезных инструментов с чуть более сложным
интерфейсом. Первый из них – sed, программируемый редактор файлов.
У него есть собственный язык программирования для автоматизированного
редактирования файлов, но чаще всего его используют так:
missing:~$ sed -i 's/pattern/replacement/g' file
Это заменяет все вхождения pattern на replacement в файле file.
Флаг -i указывает, что замены нужно сделать прямо в файле (а не
оставить file нетронутым и вывести содержимое с заменами). s/ – это
способ сказать на языке sed, что мы хотим выполнить подстановку. /
отделяет шаблон от замены. А завершающий /g означает, что мы хотим
заменить все вхождения в каждой строке, а не только первое. Как и в
случае с grep, pattern здесь – регулярное выражение, что даёт вам
немалую выразительную мощь. Подстановки с регулярными выражениями также
позволяют replacement ссылаться на части совпавшего шаблона; пример мы
увидим через мгновение.
Далее – find, которая позволяет находить файлы (рекурсивно),
удовлетворяющие определённым условиям. Например:
missing:~$ find ~/Downloads -type f -name "*.zip" -mtime +30
Находит в каталоге загрузок ZIP-файлы старше 30 дней.
missing:~$ find ~ -type f -size +100M -exec ls -lh {} \;
Находит в вашем домашнем каталоге файлы больше 100M и выводит их список.
Обратите внимание, что -exec принимает команду, завершённую отдельно
стоящим ; (который нужно экранировать, как и пробел), где {} find
заменяет на путь к каждому найденному файлу.
missing:~$ find . -name "*.py" -exec grep -l "TODO" {} \;
Находит все .py-файлы, в которых есть пункты TODO.
Синтаксис find может поначалу пугать, но, надеемся, эти примеры дали
вам представление о том, насколько она может быть полезна!
Подумайте о том, чтобы установить
fdи использовать её вместоfind– она куда дружелюбнее к человеку (но менее переносима!).
Следующая на очереди – awk, у которой, как и у sed, есть собственный
язык программирования. Если sed создана для редактирования файлов, то
awk – для их разбора. Чаще всего awk применяют к файлам данных с
регулярным синтаксисом (вроде CSV-файлов), когда нужно извлечь только
определённые части каждой записи (то есть строки):
missing:~$ awk '{print $2}' file
Выводит второй столбец (разделитель – пробельные символы) каждой строки
file. Если добавить -F,, будет выводиться второй столбец каждой
строки, разделённой запятыми. awk умеет гораздо больше – фильтровать
строки, вычислять агрегаты и не только – загляните в упражнения, чтобы
попробовать.
Соединив эти инструменты вместе, можно делать изящные вещи вроде такой:
missing:~$ ssh myserver 'journalctl -u sshd -b-1 | grep "Disconnected from"' \
| sed -E 's/.*Disconnected from .* user (.*) [^ ]+ port.*/\1/' \
| sort | uniq -c \
| sort -nk1,1 | tail -n10 \
| awk '{print $2}' | paste -sd,
postgres,mysql,oracle,dell,ubuntu,inspur,test,admin,user,root
Эта команда забирает логи SSH с удалённого сервера (об ssh мы подробнее
поговорим в следующей лекции), ищет сообщения об отключении, извлекает из
каждого такого сообщения имя пользователя и выводит 10 самых частых имён
через запятую. И всё это одной командой! Разбор каждого шага оставим в
качестве упражнения.
Язык командной оболочки (bash)
В предыдущем примере появилось новое понятие: конвейеры (pipes, |).
Они позволяют соединять вывод одной программы со входом другой. Это
работает потому, что большинство программ командной строки, если им не
передан аргумент file, читают свой «стандартный ввод» (куда обычно
попадают нажатия клавиш). | берёт «стандартный вывод» (то, что обычно
печатается в терминал) программы слева от | и делает его стандартным
вводом программы справа от |. Это позволяет компоновать
shell-программы, и именно это отчасти делает оболочку такой продуктивной
средой для работы!
На самом деле большинство оболочек реализуют полноценный язык программирования (как bash) – точно так же, как Python или Ruby. В нём есть переменные, условия, циклы и функции. Выполняя команды в оболочке, вы на самом деле пишете маленький кусочек кода, который оболочка интерпретирует. Мы не будем сегодня учить вас всему bash, но кое-что окажется для вас особенно полезным:
Во-первых, перенаправления: >file позволяет взять стандартный вывод
программы и записать его в file вместо терминала. Так его проще
анализировать постфактум. >>file дописывает в конец file, а не
перезаписывает его. Есть ещё <file, которое велит оболочке читать
стандартный ввод программы из file, а не с клавиатуры.
Самое время упомянуть программу
tee.teeпечатает стандартный ввод на стандартный вывод (совсем какcat!), но вдобавок записывает его в файл. Так чтоverbose cmd | tee verbose.log | grep CRITICALсохранит полный подробный лог в файл, а ваш терминал при этом останется чистым!
Далее, условия: if command1; then command2; command3; fi выполнит
command1 и, если та не завершится ошибкой, запустит command2 и
command3. При желании можно добавить и ветку else. Чаще всего в роли
command1 используют команду test, которую нередко сокращают просто
до [; она позволяет проверять условия вроде «существует ли файл»
(test -f file / [ -f file ]) или «равна ли одна строка другой»
([ "$var" = "string" ]). В bash есть ещё [[ ]] – «более безопасная»
встроенная версия test, у которой меньше странностей с кавычками.
В bash есть также два вида циклов: while и for. while command1; do
command2; command3; done работает точно так же, как соответствующая
команда if, только повторяет всё это снова и снова до тех пор, пока
command1 не завершается ошибкой. for varname in a b c d; do
command; done выполняет command четыре раза, каждый раз с
$varname, установленной в одно из значений a, b, c и d.
Вместо явного перечисления элементов вы часто будете использовать
«подстановку команд» (command substitution), например:
for i in $(seq 1 10); do
Это выполняет команду seq 1 10 (которая печатает числа от 1 до 10
включительно), а затем подставляет вывод этой команды вместо всего
$(), и получается цикл for на 10 итераций. В старом коде иногда
встречаются буквальные обратные кавычки (вроде for i in `seq 1 10`; do)
вместо $(), но вам стоит решительно предпочесть форму $(), поскольку
её можно вкладывать.
Хотя длинные shell-скрипты можно писать прямо в приглашении командной
строки, обычно вы будете записывать их в файл .sh. Вот, например,
скрипт, который запускает программу в цикле, пока она не упадёт,
печатает вывод только неудачного запуска и при этом нагружает процессор
в фоне (полезно, например, для воспроизведения нестабильных (flaky)
тестов):
#!/bin/bash
set -euo pipefail
# Start CPU stress in background
stress --cpu 8 &
STRESS_PID=$!
# Setup log file
LOGFILE="test_runs_$(date +%s).log"
echo "Logging to $LOGFILE"
# Run tests until one fails
RUN=1
while cargo test my_test > "$LOGFILE" 2>&1; do
echo "Run $RUN passed"
((RUN++))
done
# Cleanup and report
kill $STRESS_PID
echo "Test failed on run $RUN"
echo "Last 20 lines of output:"
tail -n 20 "$LOGFILE"
echo "Full log: $LOGFILE"
В нём много нового, и я рекомендую потратить время и разобраться в этом,
потому что всё это очень пригодится при составлении полезных
shell-команд: фоновые задания (&) для одновременного запуска программ,
более хитрые перенаправления в
оболочке
и арифметическая
подстановка.
Впрочем, стоит на секунду задержаться на первых двух строках программы.
Первая – это «шебанг» (shebang); вы увидите его в начале не только
shell-скриптов, но и других файлов. Когда выполняется файл, начинающийся
с магического заклинания #!/path, оболочка запускает программу по пути
/path и передаёт ей содержимое файла на вход. В случае shell-скрипта
это означает передачу содержимого скрипта в /bin/bash, но можно писать
и скрипты на Python со строкой шебанга /usr/bin/python!
Вторая строка – способ сделать bash «строже» и обезвредить ряд граблей
(footguns), на которые легко наступить при написании shell-скриптов.
set принимает массу аргументов, но вкратце: -e заставляет скрипт
завершиться досрочно, если любая команда завершилась с ошибкой; -u
делает так, что обращение к неопределённой переменной роняет скрипт,
вместо того чтобы просто подставить пустую строку; а -o
pipefail – так, что если программы в цепочке | завершаются с ошибкой,
shell-скрипт в целом тоже завершается досрочно.
Программирование на shell – глубокая тема, как и любой язык программирования, но имейте в виду: у bash необычайно много подводных камней – настолько, что существует несколько сайтов, целиком посвящённых их перечислению. Очень рекомендую вовсю пользоваться shellcheck, когда пишете скрипты. LLM тоже отлично справляются с написанием и отладкой shell-скриптов, а также с их переводом на «настоящий» язык программирования (вроде Python), когда они разрастаются настолько, что bash уже не тянет (100+ строк).
Что дальше
К этому моменту вы достаточно освоились в оболочке, чтобы решать базовые задачи. Вы должны уметь перемещаться по системе, находить нужные файлы и пользоваться основными возможностями большинства программ. В следующей лекции мы поговорим о том, как выполнять и автоматизировать более сложные задачи с помощью оболочки и множества удобных программ командной строки.
Упражнения
Все занятия этого курса сопровождаются набором упражнений. Некоторые ставят конкретную задачу, другие – открытые, вроде «попробуйте программы X и Y». Мы настоятельно рекомендуем их выполнить.
Решений к упражнениям мы не писали. Если вы застряли на чём-то
конкретном, смело пишите в канал #missing-semester-forum
в Discord или отправьте нам письмо с
описанием того, что уже пробовали, – мы постараемся помочь. Эти
упражнения, скорее всего, хорошо подойдут и как начальные промпты в
разговоре с LLM, где можно интерактивно погрузиться в тему. Настоящая
ценность упражнений – в пути к ответу, а не в самом ответе. Мы
призываем вас по ходу дела уходить в сторону и спрашивать «почему», а не
просто искать кратчайший путь к решению.
-
Для этого курса вам понадобится Unix-оболочка вроде Bash или ZSH. Если вы на Linux или macOS, ничего особенного делать не нужно. Если вы на Windows, убедитесь, что запускаете не cmd.exe и не PowerShell; чтобы пользоваться Unix-инструментами командной строки, можно взять Windows Subsystem for Linux или виртуальную машину с Linux. Чтобы проверить, что у вас подходящая оболочка, выполните команду
echo $SHELL. Если она выведет что-то вроде/bin/bashили/usr/bin/zsh, значит, вы запустили нужную программу. -
Что делает флаг
-lуls? Выполнитеls -l /и изучите вывод. Что означают первые 10 символов каждой строки? (Подсказка:man ls) -
В команде
find ~/Downloads -type f -name "*.zip" -mtime +30*.zip– это «glob». Что такое glob? Создайте тестовый каталог с несколькими файлами и поэкспериментируйте с шаблонами вродеls *.txt,ls file?.txtиls {a,b,c}.txt. См. раздел Pattern Matching в руководстве по Bash. -
В чём разница между
'single quotes',"double quotes"и$'ANSI quotes'? Напишите команду, которая выводит строку, содержащую буквальный$,!и символ перевода строки. См. Quoting. -
У оболочки есть три стандартных потока: stdin (0), stdout (1) и stderr (2). Выполните
ls /nonexistent /tmpи перенаправьте stdout в один файл, а stderr – в другой. Как перенаправить оба в один и тот же файл? См. Redirections. -
$?хранит код возврата последней команды (0 = успех).&&запускает следующую команду, только если предыдущая завершилась успешно;||– только если предыдущая завершилась с ошибкой. Напишите однострочник, который создаёт/tmp/mydir, только если его ещё нет. См. Exit Status. -
Почему
cdобязана быть встроена в саму оболочку, а не быть отдельной программой? (Подсказка: подумайте, на что дочерний процесс может и на что не может повлиять в родительском.) -
Напишите скрипт, который принимает имя файла аргументом (
$1) и проверяет, существует ли файл, с помощьюtest -fили[ -f ... ]. Он должен печатать разные сообщения в зависимости от того, существует файл или нет. См. Bash Conditional Expressions. -
Сохраните скрипт из предыдущего упражнения в файл (например,
check.sh). Попробуйте запустить его как./check.sh somefile. Что происходит? Теперь выполнитеchmod +x check.shи попробуйте снова. Почему этот шаг необходим? (Подсказка: посмотрите наls -l check.shдо и послеchmod.) -
Что произойдёт, если добавить
-xк флагамsetв скрипте? Попробуйте на простом скрипте и посмотрите на вывод. См. The Set Builtin. -
Напишите команду, которая копирует файл в резервную копию с сегодняшней датой в имени (например,
notes.txt→notes_2026-01-12.txt). (Подсказка:$(date +%Y-%m-%d)). См. Command Substitution. -
Измените скрипт для нестабильного (flaky) теста из лекции так, чтобы он принимал тестовую команду аргументом, а не содержал жёстко прописанное
cargo test my_test. (Подсказка:$1или$@). См. Special Parameters. -
С помощью конвейеров найдите 5 самых частых расширений файлов в вашем домашнем каталоге. (Подсказка: скомбинируйте
find,grep, илиsed, илиawk,sort,uniq -cиhead.) -
xargsпревращает строки из stdin в аргументы команды. Используйтеfindвместе сxargs(а неfind -exec), чтобы найти все файлы.shв каталоге и посчитать строки в каждом с помощьюwc -l. Бонус: сделайте так, чтобы это работало с именами файлов, содержащими пробелы. (Подсказка:-print0и-0). См.man xargs. -
С помощью
curlполучите HTML сайта курса (https://missing.csail.mit.edu/) и передайте его по конвейеру вgrep, чтобы посчитать, сколько лекций там перечислено. (Подсказка: поищите шаблон, который встречается по одному разу на лекцию; используйтеcurl -s, чтобы отключить вывод прогресса.) -
jq– мощный инструмент для обработки данных в формате JSON. Скачайте с помощьюcurlтестовые данные по адресуhttps://microsoftedge.github.io/Demos/json-dummy-data/64KB.jsonи с помощьюjqизвлеките только имена людей, у которых версия (version) больше 6. (Подсказка: сначала передайте данные вjq ., чтобы увидеть структуру; затем попробуйтеjq '.[] | select(...) | .name') -
awkумеет фильтровать строки по значениям столбцов и менять вывод. Например,awk '$3 ~ /pattern/ {$4=""; print}'печатает только те строки, в которых третий столбец совпадает сpattern, опуская при этом четвёртый столбец. Напишите командуawk, которая печатает только строки, где второй столбец больше 100, и меняет местами первый и третий столбцы. Проверьте на:printf 'a 50 x\nb 150 y\nc 200 z\n' -
Разберите по шагам конвейер с логами SSH из лекции: что делает каждый шаг? Затем соберите что-то похожее, чтобы найти самые часто используемые вами команды оболочки по
~/.bash_history(или~/.zsh_history).
Лицензия CC BY-NC-SA.