# Решения ## 1 Повторите структуру директории с помощью команд `mkdir` и `touch`: ``` mkdir project cd project mkdir backup mkdir data mkdir data/raw/ touch data/raw/2022-07-23-exp1.data touch data/raw/2022-07-23-exp1.log touch data/raw/2022-08-03-exp2.calib touch data/raw/2022-08-03-exp2.data touch data/raw/2022-08-03-exp2.log touch data/raw/2022-11-23-exp3.calib touch data/raw/2022-11-23-exp3.data touch data/raw/2022-11-23-exp3.log mkdir shared mkdir -p this/is/a/long/and/strange/path ``` ## 2 Вы в директории `/home/stud/project/`. Какая из команд переместит вас в домашнюю директорию? ``` 3 cd /home/stud 5 cd ~ 7 cd ~/data/.. 8 cd 9 cd .. ``` ## 3 Перейдите в папку `backup`. Используя команду `cp`, выполните следующие действия одной строкой: - скопируйте два файла: `.bashrc` и `.bash_profile` в папку `backup`, - скопируйте файл `.bashrc` в две директории: `/tmp/` и `shared`. ``` cd ~/project/backup/ cp -t ./ ~/.bashrc ~/.bash_profile cp ~/.bashrc/ /tmp/ cp ~/.bashrc /home/stud/project/shared/ ``` ## 4 Создайте файл `dummy` в `/tmp`. Попробуйте удалить его указав флаг `-i` для команды `rm`. В чём отличие удаления файла с этим флагом и без него? ``` mkdir /tmp/dummy rm -r -i /tmp/dummy rm: remove directory '/tmp/dummy'? y rm -r /tmp/dummy ``` Отличие в запросе подтверждения действия. ## 5 Скопируйте файлы экспериментов в `backup`, но распределите их по папкам. Файлы с расширением `.datа` в `backup/data`, файлы с расширением `.calib` в `backup/calibration`, логи `.log` в `backup/logs`. В `shared` поместите все файлы, созданные 23 числа в папку `23day`. Напишите команды в двух вариантах: с относительными путями и с абсолютными и проверьте, что их выполнение даёт одинаковый результат. ``` cd backup mkdir data calibration logs 23day cp ../raw/*.data ./data/ cp /home/stud/project/raw/*.calib /home/stud/project/backup/calibration cp /home/stud/project/raw/*.log /home/stud/project/backup/logs/ cp /home/stud/project/raw/*-23-* /home/stud/project/backup/23day/ ``` ## 6 Посчитайте количество строк, слов и символов в файле `/var/log/dpkg.log`. ``` wc -l /var/log/dpkg.log cat /var/log/dpkg.log | wc -l wc -w /var/log/dpkg.log wc -m /var/log/dpkg.log ``` ## 7 Инициализируйте файл `head_tail_messages` с помощью команды `head` из строк в `/var/log/dpkg.log`. Затем добавьте в `head_tail_messages` последние 23 строки из `/var/log/dpkg.log`. ``` sudo head /var/log/dpkg.log > head_tail_messages sudo tail -n 23 /var/log/dpkg.log >> head_tail_messages ``` ## 8 Постройте конвейр с помощью оператора `|`, который считывает содержимое `/var/log/dpkg.log`, находит только строки содержащие слово `perl`, сохраняет результат в файл `/tmp/perl_pkgs` и одновременно выводит в консоль количество найденных строк. ``` cat /var/log/dpkg.log | grep perl | tee /tmp/perl_pkgs | wc -l ``` ## 9 Выполните две команды: `head /nonexistent; echo Ok` и `head /nonexistent && echo Ok`. В чём отличие в поведении? В первом случае вторая команда выполнится, несмотря на не нулевой код ошибки. Во втором не выполнится, в консоли не напечатается "Ok". ## 10 Оператор `||` похож на оператор ИЛИ в программировании. Что вы ожидаете увидеть при запуске `mkdir test || echo Ok`? Проверьте так ли это. Так как первая команда выполнится успешно, значение выражения можно считать истинным даже если другие будут выполнятся с ошибками. Поэтому вторая команда выполняться не будет. ## 11 Создайте псевдонимы: `dc`, `chomd` которые разрешаются в команды: `cd`, `chmod` чтобы наконец решить проблему опечаток. Создайте псевдоним `ls` для команды `ls -alF` и `cdw` для команды `cd /home/stud/project/`. Проверьте работу псевдонимов. Удалите псевдоним `ls` командой `unalias`. Проверьте, что выдача соответствует оригинальной команде `ls`. ``` alias dc="cd" alias chomd="chmod" alias ls="ls -alF" alias cdw="cd /home/stud/project/" unalias ls ``` ## 12 Прочитайте мануал `man ls` и напишите `ls` команду, которая выводит список файлов в следующем виде: * список файлов включает скрытые, * размер файла указан с метрическими приставками (e.g. 454M вместо 454279954), * файлы выводятся в историческом порядке, * вывод в цвете. ``` ls -caht или ls -cahtl ``` ## 13 Попробуйте вывести содержимое переменной среды `HOME` с помощью `echo` в одинарных и двойных кавычках. В чём разница? ``` echo "$HOME" echo '$HOME' ``` Разница в том, что выражения внутри двойных кавычек интерпретируются, а в одинарных нет. В первом случае выведется значение переменной HOME, во втором `$HOME`. ## 14 Запишите в переменную среды `PATH` значение `""`. Как это повлияло на выполнение команд? Перелогиньтесь и попробуйте вызывать любую команду заново. Сохранилиcь ли изменения? Первое слово в консоли интерпретируется как вызов исполняемого файла, функции или псевдонима. Поиск исполняемых файлов с переданным названием ведётся в директориях, перечисленных через `:` в переменной среды PATH. Поэтому при пустом списке ни один исполняемый файл не будет найден. ``` export PATH=”” следствие: ни один исполняемый файл системой теперь не находится после переподключения система вернулась в прежнее состояние ``` ## 15 C помощью bash синтаксиса для арифметических операций выведите результат: - сложения 10 и 4, - умножения 10 на 4, - деления 10 на b, где b это переменная равная 3. Сохраните результат операции `a % b` в переменную `c`, где `a` и `b` результаты любых предыдущих двух операций. Выведите `с`. ``` echo $((10 + 4)) echo $((10 * 4)) b=3 echo $((10 / b)) a=$((10 * 4)) b=$((10 / b)) c=$((a % b)) echo $c ``` ## 16 Выполните в терминале следующую команду в директории `/tmp`: ``` for species in cubane ethane methane; do for temperature in 25 30 37 40; do mkdir $species-$temperature; done done ``` Что в результате вы видите в консоли? Модифицируйте команду так, чтобы у директорий в начале названия присутствовал глобальный индекс `idx`. На каждой итерации внутреннего цикла `idx` должна увеличиваться на единицу. ``` idx=0; for species in cubane ethane methane; do for temperature in 25 30 37 40; do mkdir $idx-$species-$temperature; ((idx+=1)); done done ``` ``` idx=-1; for species in cubane ethane methane; do for temperature in 25 30 37 40; do mkdir $idx-$species-$temperature; ((idx+=1)); done; done ``` ## 17 Напишите цикл, который проходит по списку файлов в текущей директории и выводит полный путь к директории и имя файла. ``` for f in `ls`; do echo `pwd` $f; done ``` ## 18 Далее поработайте с командой `watch date`. Команда `watch` вызывает периодически переданную ей команду в качестве аргумента. Это удобно для организации простого мониторинга. Первый раз вызовите команду и отправьте процессу сигнал `SIGINT` комбинацией клавишь `Ctrl+C`. Второй раз вызовите команду и отправьте процессу сигнал `SIGTSTP` комбинацией клавишь `Ctrl+Z`. Выведите статус процесса командой `jobs`. Переведите процесс в активное состояние командой `fg` и остановите процесс. Третий раз вызовите команду с добавлением одиночного символа `&`. Остановите процесс командой `kill`. *man страницы: kill, signal* Механизм сигналов - примитивный способ общения с процессами. Часть кодов сигналов процесс обязан обработать, часть может обработать исходя из заданной программистом логики. При запуске процесса в интерактивном режиме его потоки ввода и вывода соединяются с терминалом. Символ & позволяет запустить процесс в фоновом режиме, не делая связывания потока ввода. ## 19 Напишите команду, которая рекурсивно находит все HTML-файлы в папке и запаковывает их в tar.gz архив. Ваша команда должна работать, даже если в файлах есть пробелы. ``` find . -type f -name "*.html" -print0 | xargs -0 tar cfz htmls.tar.gz ``` ## 20 (*) Напишите команду или сценарий для рекурсивного поиска самого последнего измененного файла в каталоге. В общем, можете ли вы перечислить все файлы по давности? Плохое решение ``` ls -Rlht ``` Лучше ``` find ./ -type f -printf "%T+ %H%P\n" 2>/dev/null | sort -r ``` где %T+ - время последнего изменения в формате 2004-04-28+22:22:05.0, %H - путь к директории, в которой файл найден, %P - имя файла.