📖 Теория — Завершение работы со скриптами

К оглавлению урока

⚡ Пять задач урока

  • Задача 1: testscript.sh — Dir1..5 + File1..5 + tar архив + распаковка
  • Задача 2: pinger.sh — read -p адрес, ping -c, awk среднее время
  • Задача 3: md5check.sh — md5sum file >> checksums.txt
  • Задача 4: скрипт-генератор — ls 2>/dev/null; if [ $? -eq 0 ]
  • Задача 5: смена расширений — [ -z ], [ ! -d ], mv file.old file.new

Задача 1 — testscript.sh: архивирование с иерархией

Скрипт создаёт структуру директорий и файлов, упаковывает их в tar-архив и распаковывает в новое место.

Алгоритм

  1. Объявить переменные для путей: ARHPATH=/tmp/Arh, EXTPATH=/opt/newfolder
  2. Получить текущую дату: DATE=`date '+%d-%m-%y'`
  3. Внешний цикл for i in {1..5}: создать Dir$i
  4. Внутренний цикл for j in {1..5}: записать время в Dir$i/File-$j.txt, пауза 5 секунд
  5. Вывести список файлов: ls Dir$i
  6. Создать архив: tar -czvf $ARHPATH/Arh-$DATE.tar.gz Dir*
  7. Записать список в файл: >> ArhList.txt (накопление, а не перезапись)
  8. Создать путь распаковки: mkdir -p $EXTPATH
  9. Распаковать с сохранением структуры: tar -xzf $ARHPATH/Arh-$DATE.tar.gz -C $EXTPATH
Флаги tar:
-c — создать архив (create)
-z — сжать через gzip
-v — вывод имён упаковываемых файлов (verbose)
-f — имя файла архива
-x — извлечь из архива
-C path — распаковать в указанный каталог
Важно: >> в строке tar
В строке tar -czvf $ARHPATH/Arh-$DATE.tar.gz Dir* >> ArhList.txt оператор >> дополняет файл ArhList.txt (не перезаписывает). Если скрипт запустить несколько раз — список будет накапливаться. Если нужна только последняя запись — используйте >.

Задача 2 — pinger.sh: ping с обработкой вывода

Команда ping в Linux используется для проверки доступности удалённого узла и измерения задержки. Она отправляет ICMP ECHO_REQUEST-пакеты и ждёт ответа.

Интерактивный ввод: read -p

read — встроенная команда bash для чтения строки из stdin. Флаг -p выводит приглашение перед вводом:

read -p "Введите адрес для пинга: " address
read -p "Введите количество запросов: " count

Получение среднего времени через awk

Вывод ping содержит строку вида: rtt min/avg/max/mdev = 1.2/3.4/5.6/0.7 ms

Извлечь среднее (avg, второе поле): awk -F'/' '/^rtt/ { print $5 }'

На macOS: строка статистики начинается с round-trip вместо rtt. Паттерн /^rtt/ работает только на Linux.

Задача 3 — MD5-хэши: контроль целостности файлов

MD5-хэш (Message Digest Algorithm 5) — криптографическая хэш-функция. Принимает на вход сообщение произвольной длины, выдаёт 128-битное хэш-значение (32 шестнадцатеричных символа).

Если MD5-хэш файла до передачи и после получения совпадают — файл не был изменён. Именно так проверяют целостность дистрибутивов Linux и других загрузок.

Команда md5sum

# Вычислить хэш одного файла
md5sum file.txt

# Записать хэш в файл (накопление)
md5sum file.txt >> checksums.txt

# Проверить файлы по ранее сохранённым хэшам
md5sum -c checksums.txt

Алгоритм скрипта

  1. read -p "Enter path for control: " pathcheck
  2. read -p "Enter path for result file: " pathresult
  3. mkdir -p $pathresult — создать директорию результата
  4. Цикл по файлам: for var in $pathcheck/*; do md5sum $pathcheck/$var >> $pathcheck-md5sum.txt; done

Задача 4 — Скрипт, создающий скрипты

Метапрограммирование: один скрипт создаёт другой скрипт с шаблонным заголовком и назначает ему права исполнения.

Проверка существования файла через $?

ls $SCRIPTPATH/$NAME 2>/dev/null
if [ $? -eq 0 ]
then
    echo "BAD NAME $NAME - file exists"
else
    echo "Script will be created: $SCRIPTPATH/$NAME"
    echo -e "#!/bin/bash\n#\n#Write the code here\n#\n" > $SCRIPTPATH/$NAME
    chmod +x $SCRIPTPATH/$NAME
    echo "DONE"
fi
$? — код возврата последней команды. 0 — успех, ненулевое — ошибка.
2>/dev/null — перенаправить stderr в /dev/null (подавить сообщение об ошибке, если файл не найден).
echo -e — интерпретировать escape-последовательности (\n → новая строка).

Задача 5 — Смена расширений файлов

Скрипт пакетно переименовывает файлы с одним расширением на другое в указанной директории.

Ключевые проверки

# Если директория не указана — использовать текущую
if [ -z "$directory" ]; then
    directory="."
fi

# Если директория не существует — ошибка
if [ ! -d "$directory" ]; then
    echo "Директория '$directory' не существует."
    exit 1
fi
Проверки:
[ -z "$var" ] — строка пустая (zero length)
[ ! -d "$dir" ] — директория НЕ существует
[ -e "$file" ] — файл существует (any type)
[ -f "$file" ] — обычный файл существует

Переименование в цикле

for file in *.$current_extension; do
    if [ -e "$file" ]; then
        filename=$(basename "$file" ".$current_extension")
        mv "$file" "$filename.$new_extension"
        echo "Изменено: $file -> $filename.$new_extension"
    fi
done