Команды для работы с файлами и архивами

12.5. Команды для работы с файлами и архивами

Архивация

tar

Стандартная, для Unix, утилита архивирования. Первоначально -- это была программа Tape ARchiving, которая впоследствии переросла в универсальный пакет, который может работать с любыми типами устройств (см. Пример 3-4). В GNU-версию tar была добавлена возможность одновременно производить сжатие tar-архива, например команда tar czvf archive_name.tar.gz * создает tar-архив дерева подкаталогов и вызывает gzip для выполнения сжатия, исключение составляют скрытые файлы в текущем каталоге ($PWD). [1]

Некоторые, часто используемые, ключи команды tar:

  1. -c -- создать (create) новый архив

  2. -x -- извлечь (extract) файлы из архива

  3. --delete -- удалить (delete) файлы из архива

    Caution

    Этот ключ игнорируется для накопителей на магнитной ленте.

  4. -r -- добавить (append) файлы в существующий архив

  5. -A -- добавить (append) tar-файлы в существующий архив

  6. -t -- список файлов в архиве (содержимое архива)

  7. -u -- обновить (update) архив

  8. -d -- операция сравнения архива с заданной файловой системой

  9. -z -- обработка архива с помощью gzip

    (Сжатие или разжатие, в зависимости от комбинации сопутствующих ключей -c или -x)

  10. -j -- обработка архива с помошью bzip2



Caution

При восстановлении "битых" tar.gz архивов могут возникнуть определенные сложности, поэтому делайте несколько резервных копий.

shar

Утилита создания shell-архива. Архивируемые файлы объединяются в единый файл без выполнения сжатия, в результате получается архив -- по сути полноценный сценарий на языке командной оболочки, начинающийся со строки #!/bin/sh, который содержит полный набор команд, необходимый для разархивирования. Такого рода архивы до сих пор можно найти в некоторых телеконференциях в Internet, но в последнее время они активно вытесняются связкой tar/gzip. Для распаковки shar-архивов предназначена команда unshar.

ar

Утилита создания и обслуживания архивов, главным образом применяется к двоичным файлам библиотек.

rpm

Red Hat Package Manager, или rpm -- набор утилит, предназначенных для построения и обслуживания пакетов программного обеспечения как в исходном коде, так и в собранном (откомпилированном) виде. Среди всего прочего, включает в себя утилиты, производящие установку ПО, проверку зависимостей пакетов и проверку их целостности.

Самый простой вариант установки ПО из rpm -- выполнить команду rpm -i package_name.rpm.

Tip

Команда rpm -qa выдаст полный список всех установленных rpm-пакетов в данной системе. Команда rpm -qa package_name выведет только пакет(ы) с именем, содержащим комбинацию символов package_name.

bash$ rpm -qa
redhat-logos-1.1.3-1
 glibc-2.2.4-13
 cracklib-2.7-12
 dosfstools-2.7-1
 gdbm-1.8.0-10
 ksymoops-2.4.1-1
 mktemp-1.5-11
 perl-5.6.0-17
 reiserfs-utils-3.x.0j-2
 ...


bash$ rpm -qa docbook-utils
docbook-utils-0.6.9-2


bash$ rpm -qa docbook | grep docbook
docbook-dtd31-sgml-1.0-10
 docbook-style-dsssl-1.64-3
 docbook-dtd30-sgml-1.0-10
 docbook-dtd40-sgml-1.0-11
 docbook-utils-pdf-0.6.9-2
 docbook-dtd41-sgml-1.0-10
 docbook-utils-0.6.9-2
        


cpio

Специализированная утилита архивации и копирования (copy input and output). Используется все реже и реже, поскольку вытесняется более мощным архиватором tar/gzip. Наиболее употребительна для таких операций, как перемещение дерева каталогов.

Пример 12-25. Пример перемещения дерева каталогов с помощью cpio

#!/bin/bash

# Копирование дерева каталогов с помощью cpio.

ARGS=2
E_BADARGS=65

if [ $# -ne "$ARGS" ]
then
  echo "Порядок использования: `basename $0` source destination"
  exit $E_BADARGS
fi

source=$1
destination=$2

find "$source" -depth | cpio -admvp "$destination"
# Информацию по ключам утилиты cpio вы найдете в страницах руководства "man cpio".

exit 0
rpm2cpio

Эта утилита конвертирует rpm-пакет в архив cpio.

Пример 12-26. Распаковка архива rpm

#!/bin/bash
# de-rpm.sh: Распаковка архива 'rpm'

: ${1?"Порядок использования: `basename $0` target-file"}
# Сценарию должно быть передано имя архива 'rpm'.


TEMPFILE=$$.cpio                         # Временный файл с "уникальным" именем.
                                         # $$ -- PID процесса сценария.

rpm2cpio < $1 > $TEMPFILE                # Конверсия из rpm в cpio.
cpio --make-directories -F $TEMPFILE -i  # Рапсковка cpio-архива.
rm -f $TEMPFILE                          # Удаление cpio-архива.

exit 0

#  Упражнение:
#  Добавьте проверку на: 1) Существование "target-file"
#+                       2) Действительно ли "target-file" является rpm-архивом.
#  Подсказка:               используйте комсанду 'file'.

Сжатие

gzip

Стандартная GNU/Unix утилита сжатия, заменившая более слабую, и к тому же проприетарную, утилиту compress. Соответствующая утилита декомпрессии (разжатия) -- gunzip, которая является эквивалентом команды gzip -d.

Для работы со сжатыми файлами в конвейере используется фильтр zcat, который выводит результат своей работы на stdout, допускает перенаправление вывода. Фактически это та же команда cat, только приспособленная для работы со сжатыми файлами (включая файлы, сжатые утилитой compress). Эквивалент команды zcat -- gzip -dc.

Caution

В некоторых коммерческих версиях Unix, команда zcat является синонимом команды uncompress -c, и не может работать с файлами, сжатыми с помощью gzip.

См. также Пример 7-7.

bzip2

Альтернативная утилита сжатия, обычно дает более высокую степень сжатия (но при этом работает медленнее), чем gzip, особенно это проявляется на больших файлах. Соответствующая утилита декомпрессии -- bunzip2.

Note

В современные версии tar добавлена поддержка bzip2.

compress, uncompress

Устаревшие проприетарные утилиты для работы с архивами, входящие в состав некоторых коммерческих дистрибутивов Unix. В последнее время вытесняются более мощной утилитой gzip. Linux-дистрибутивы, как правило, включают в свой состав эти утилиты для обратной совместимости, однако gunzip корректно разархивирует файлы, обработанные с помощью compress.

Tip

Утилита znew предназначена для преобразования compress-архивов в gzip-архивы.

sq

Еще одна утилита-фильтр сжатия, которая обслуживает только отсортированные списки слов. Использует стандартный, для фильтров, синтаксис вызова -- sq < input-file > output-file. Быстрая, но не такая эффективная как gzip. Соответствующая ей утилита декомпрессии называется unsq, синтаксис вызова аналогичен утилите sq.

Tip

Вывод от sq может быть передан по конвейеру утилите gzip, для дальнейшего сжатия.

zip, unzip

Кроссплатформенная утилита архивирования и сжатия, совместимая, по формату архивного файла, с утилитой DOS -- pkzip.exe. "Zip"-архивы, по-моему, более приемлемый вариант для обмена данными через Internet, чем "tarballs" (тарболлы, или tar-архивы).

unarc, unarj, unrar

Этот набор утилит предназначен для распаковки архивов, созданных с помощью DOS архиваторов -- arc.exe, arj.exe и rar.exe.

Получение сведений о файлах

file

Утилита идентификации файлов. Команда file file-name верне тип файла file-name, например, ascii text или data. Для этого она анализирует сигнатуру, или магическое число и сопоставляет ее со списком известных сигнатур из /usr/share/magic, /etc/magic или /usr/lib/magic (в зависимости от дистрибутива Linux/Unix).

-f -- ключ пакетного режима работы утилиты file, в этом случае утилита принимает список анализируемых имен файлов из заданного файла. Ключ -z используется для анализа файлов в архиве.

bash$ file test.tar.gz
test.tar.gz: gzip compressed data, deflated, last modified: Sun Sep 16 13:34:51 2001, os: Unix

bash file -z test.tar.gz
test.tar.gz: GNU tar archive (gzip compressed data, deflated, last modified: Sun Sep 16 13:34:51 2001, os: Unix)
        


Пример 12-27. Удаление комментариев из файла с текстом программы на языке C

#!/bin/bash
# strip-comment.sh: Удаление комментариев (/* COMMENT */) из исходных текстов программ на языке C.

E_NOARGS=65
E_ARGERROR=66
E_WRONG_FILE_TYPE=67

if [ $# -eq "$E_NOARGS" ]
then
  echo "Порядок использования: `basename $0` C-program-file" >&2 # Вывод сообщения на stderr.
  exit $E_ARGERROR
fi

# Проверка типа файла.
type=`eval file $1 | awk '{ print $2, $3, $4, $5 }'`
# "file $1" -- выводит тип файла...
# затем awk удаляет первое поле -- имя файла...
# после этого результат записывается в переменную "type".
correct_type="ASCII C program text"

if [ "$type" != "$correct_type" ]
then
  echo
  echo "Этот сценарий работает только с исходными текстами программ на языке C."
  echo
  exit $E_WRONG_FILE_TYPE
fi


# Довольно замысловатый сценарий sed :
#--------
sed '
/^\/\*/d
/.*\/\*/d
' $1
#--------
# Если вы потратите несколько часов на изучение основ sed, то он станет немного понятнее.


#  Следовало бы добавить еще обработку
#+ комментариев, расположенных в одной строке с кодом.
#  Оставляю это вам, в качестве упражнения.

# Кроме того, этот сценарий удалит все строки, которые содержат комбинации символов "*/" или "/*",
# не всегда желаемый результат.

exit 0


# ----------------------------------------------------------------
# Строки, расположенные ниже не будут исполнены из-за стоящей выше команды 'exit 0'.

# Stephane Chazelas предложил другой, альтернативный вариант:

usage() {
  echo "Порядок использования: `basename $0` C-program-file" >&2
  exit 1
}

WEIRD=`echo -n -e '\377'`   # или WEIRD=$'\377'
[[ $# -eq 1 ]] || usage
case `file "$1"` in
  *"C program text"*) sed -e "s%/\*%${WEIRD}%g;s%\*/%${WEIRD}%g" "$1" \
     | tr '\377\n' '\n\377' \
     | sed -ne 'p;n' \
     | tr -d '\n' | tr '\377' '\n';;
  *) usage;;
esac

# Этот вариант, все еще некорректно обрабатывает такие строки как:
# printf("/*");
# или
# /*  /* ошибочный вложенный комментарий */
#
# Для обработки специальных случаев (\", \\" ...) придется написать синтаксический анализатор
# (может быть с помощью lex или yacc?).

exit 0
which

Команда which command-xxx вернет полный путь к "command-xxx". Очень полезна для того, чтобы узнать -- установлена ли та или иная утилита в системе.

$bash which rm

/usr/bin/rm


whereis

Очень похожа на which, упоминавшуюся выше. Команда whereis command-xxx вернет полный путь к "command-xxx", но кроме того, еще и путь к manpage -- файлу, странице справочника по заданной утилите.

$bash whereis rm

rm: /bin/rm /usr/share/man/man1/rm.1.bz2


whatis

Утилита whatis filexxx отыщет "filexxx" в своей базе данных. Может рассматриваться как упрощенный вариант команды man.

$bash whatis whatis

whatis               (1)  - search the whatis database for complete words


Пример 12-28. Исследование каталога /usr/X11R6/bin

#!/bin/bash

# Что находится в каталоге /usr/X11R6/bin?

DIRECTORY="/usr/X11R6/bin"
# Попробуйте также "/bin", "/usr/bin", "/usr/local/bin", и т.д.

for file in $DIRECTORY/*
do
  whatis `basename $file`   # Вывод информации о файле.
done

exit 0
# Вывод этого сценария можно перенаправить в файл:
# ./what.sh >>whatis.db
# или включить постраничный просмотр на экране,
# ./what.sh | less

См. также Пример 10-3.

vdir

Вывод списка файлов в каталоге. Тот же эффект имеет команда ls -l.

Это одна из утилит GNU fileutils.

bash$ vdir
total 10
 -rw-r--r--    1 bozo  bozo      4034 Jul 18 22:04 data1.xrolo
 -rw-r--r--    1 bozo  bozo      4602 May 25 13:58 data1.xrolo.bak
 -rw-r--r--    1 bozo  bozo       877 Dec 17  2000 employment.xrolo

bash ls -l
total 10
 -rw-r--r--    1 bozo  bozo      4034 Jul 18 22:04 data1.xrolo
 -rw-r--r--    1 bozo  bozo      4602 May 25 13:58 data1.xrolo.bak
 -rw-r--r--    1 bozo  bozo       877 Dec 17  2000 employment.xrolo
        


locate, slocate

Команда locate определяет местонахождение файла, используя свою базу данных, создаваемую специально для этих целей. Команда slocate -- это защищенная версия locate (которая может оказаться простым псевдонимом команды slocate).

$bash locate hickson

/usr/lib/xephem/catalogs/hickson.edb


readlink

Возвращает имя файла, на который указывает символическая ссылка.

bash$ readlink /usr/bin/awk
../../bin/gawk
        


strings

Команда strings используется для поиска печатаемых строк в двоичных файлах. Она выводит последовательности печатаемых символов, обнаруженных в заданном файле. Может использоваться для прикидочного анализа дамп-файлов (core dump) или для отыскания информации о типе файла, например для графических файлов неизвестного формата (например, strings image-file | more может вывести такую строчку: JFIF, что говорит о том, что мы имеем дело с графическим файлом в формате jpeg). В сценариях, вероятнее всего, вам придется использовать эту команду в связке с grep или sed. См. Пример 10-7 и Пример 10-9.

Пример 12-29. "Расширенная" команда strings

#!/bin/bash
# wstrings.sh: "word-strings" (расширенная команда "strings")
#
#  Этот сценарий фильтрует вывод команды "strings" путем проверки на соответствие
#+ выводимых слов по файлу словаря.
#  Таким способом эффективно "отсекается" весь "мусор",
#+ и выводятся только распознанные слова.

# =================================================================
#                 Стандартная проверка входных аргументов
ARGS=1
E_BADARGS=65
E_NOFILE=66

if [ $# -ne $ARGS ]
then
  echo "Порядок использования: `basename $0` filename"
  exit $E_BADARGS
fi

if [ ! -f "$1" ]                      # Проверка наличия файла.
then
    echo "Файл \"$1\" не найден."
    exit $E_NOFILE
fi
# =================================================================


MINSTRLEN=3                           #  Минимальная длина строки.
WORDFILE=/usr/share/dict/linux.words  #  Файл словаря.
                                      #  Можно указать иной
                                      #+ файл словаря
                                      #+ в формате -- "одно слово на строке".


wlist=`strings "$1" | tr A-Z a-z | tr '[:space:]' Z | \
tr -cs '[:alpha:]' Z | tr -s '\173-\377' Z | tr Z ' '`

# Трансляция вывода от 'strings' с помощью нескольких 'tr'.
#  "tr A-Z a-z"  -- перевод в нижний регистр.
#  "tr '[:space:]'"  -- конвертирует пробелы в символы Z.
#  "tr -cs '[:alpha:]' Z"  -- конвертирует неалфавитные символы в символы Z,
#+ и удаляет повторяющиеся символы Z.
#  "tr -s '\173-\377' Z"  -- Конвертирует все символы, с кодами выше 'z' в Z
#+ и удаляет повторяющиеся символы Z,
#+ эта команда удалит все символы, которые не были распознаны предыдущими
#+ командами трансляции (tr).
#  Наконец, "tr Z ' '" -- преобразует все символы Z в пробелы,
#+ которые будут рассматриваться в качестве разделителя слов в цикле, приведенном ниже.

#  Обратите внимание на технику многоуровневой обработки с помощью 'tr',
#+ каждый раз эта команда вызывается с различным набором аргументов.


for word in $wlist                    # Важно:
                                      # переменная $wlist не должна заключаться в кавычки.
                                      # "$wlist" -- не сработает.
                                      # Почему?
do

  strlen=${#word}                     # Дина строки.
  if [ "$strlen" -lt "$MINSTRLEN" ]   # Не рассматривать короткие строки.
  then
    continue
  fi

  grep -Fw $word "$WORDFILE"          # Проверка слова по словарю.

done


exit 0

Сравнение

diff, patch

diff: очень гибкая утилита сравнения файлов. Она выполняет построчное сравнение файлов. В отдельных случаях, таких как поиск по словарю, может оказаться полезной фильтрация файлов с помощью sort и uniq перед тем как отдать поток данных через конвейер утилите diff. diff file-1 file-2 -- выведет строки, имеющие отличия, указывая -- какому файлу, какая строка принадлежит.

С ключом --side-by-side, команда diff выведет сравниваемые файлы в две колонки, с указанием несовпадающих строк. Ключи -c и -u так же служат для облегчения интерпретации результатов работы diff.

Существует ряд интерфейсных оболочек для утилиты diff, среди них можно назвать: spiff, wdiff, xdiff и mgdiff.

Tip

Команда diff возвращает код завершения 0, если сравниваемые файлы идентичны и 1, если они отличаются. Это позволяет использовать diff в условных операторах внутри сценариев на языке командной оболочки (см. ниже).

В общем случае, diff используется для генерации файла различий, который используется как аргумент команды patch. Ключ -e отвечает за вывод файла различий в формате, пригодном для использования с ed или ex.

patch: гибкая утилита для "наложения заплат". С помощью файла различий, сгенерированного утилитой diff, утилита patch может использоваться для обновления устаревших версий файлов. Это позволяет распространять относительно небольшие "diff"-файлы вместо целых пакетов. Распространение "заплат" к ядру стало наиболее предпочтительным методом распространения более новых версий ядра Linux.

patch -p1 <patch-file
# Применит все изменения из 'patch-file'
# к файлам, описанным там же.
# Так выполняется обновление пакетов до более высоких версий.


Наложение "заплат" на ядро:

cd /usr/src
gzip -cd patchXX.gz | patch -p0
# Обновление исходных текстов ядра с помощью 'patch'.
# Пример взят из файла "README",
# автор не известен (Alan Cox?).


Note

Кроме того, утилита diff в состоянии выполнять рекурсивный обход каталогов.

bash$ diff -r ~/notes1 ~/notes2
Only in /home/bozo/notes1: file02
 Only in /home/bozo/notes1: file03
 Only in /home/bozo/notes2: file04
        


Tip

Утилита zdiff сравнивает сжатые, с помощью gzip, файлы.

diff3

Расширенная версия diff, которая сравнивает сразу 3 файла. В случае успеха возвращает 0, но, к сожалению, не дает никакой информации о результатах сравнения.

bash$ diff3 file-1 file-2 file-3
====
 1:1c
   This is line 1 of "file-1".
 2:1c
   This is line 1 of "file-2".
 3:1c
   This is line 1 of "file-3"
        


sdiff

Сравнение и/или редактирование двух файлов перед объединением их в один файл. Это интерактивная утилита, по своей природе, и из-за этого она довольно редко используется в сценариях.

cmp

Утилита cmp -- это упрощенная версия diff. В то время, как diff выводит подробную информацию об имеющихся различиях, утилита cmp лишь показывет номер строки и позицию в строке, где было встречено различие.

Note

Подобно команде diff, команда cmp возвращает код завершения 0, если файлы идентичны и 1, если они различны. Это позволяет использовать команду cmp в условных операторах.

Пример 12-30. Пример сравнения двух файлов с помощью cmp.

#!/bin/bash

ARGS=2  # Ожидаются два аргумента командной строки.
E_BADARGS=65
E_UNREADABLE=66

if [ $# -ne "$ARGS" ]
then
  echo "Порядок использования: `basename $0` file1 file2"
  exit $E_BADARGS
fi

if [[ ! -r "$1" || ! -r "$2" ]]
then
  echo "Оба файла должны существовать и должны быть доступны для чтения."
  exit $E_UNREADABLE
fi

cmp $1 $2 &> /dev/null  # /dev/null -- "похоронит" вывод от команды "cmp".
#   cmp -s $1 $2  даст тот же результат ("-s" -- флаг "тишины" для "cmp")
#   Спасибо Anders Gustavsson за замечание.
#
# Также применимо к 'diff', т.е.,   diff $1 $2 &> /dev/null

if [ $? -eq 0 ]         # Проверка кода возврата команды "cmp".
then
  echo "Файл \"$1\" идентичен файлу \"$2\"."
else
  echo "Файл \"$1\" отличается от файла \"$2\"."
fi

exit 0
Tip

Для работы с gzip файлами используется утилита zcmp.

comm

Универсальная утилита сравнения. Работает с отсортированными файлами.

comm -options first-file second-file

comm file-1 file-2 -- вывод в три колонки:

  • колонка 1 = уникальные строки для file-1

  • колонка 2 = уникальные строки для file-2

  • колонка 3 = одинаковые строки.



Ключи, подавляющие вывод в одной или более колонках.

  • -1 -- подавление вывода в колонку 1

  • -2 -- подавление вывода в колонку 2

  • -3 -- подавление вывода в колонку 3

  • -12 -- подавление вывода в колонки 1 и 2, и т.д.



Утилиты

basename

Выводит только название файла, без каталога размещения. Конструкция basename $0 -- позволяет сценарию узнать свое имя, то есть имя файла, который был запущен. Это имя может быть использовано для вывода сообщений, напрмиер:

echo "Порядок использования: `basename $0` arg1 arg2 ... argn"


dirname

Отсекает basename от полного имени файла и выводит только путь к файлу.

Note

Утилитам basename и dirname может быть передана любая строка, в качестве аргумента. Этот аргумент необязательно должен быть именем существующего файла (см. Пример A-8).

Пример 12-31. Утилиты basename и dirname

#!/bin/bash

a=/home/bozo/daily-journal.txt

echo "Basename для /home/bozo/daily-journal.txt = `basename $a`"
echo "Dirname для /home/bozo/daily-journal.txt = `dirname $a`"
echo
echo "Мой домашний каталог `basename ~/`."             # Можно указать просто ~.
echo "Каталог моего домашнего каталога `dirname ~/`."  # Можно указать просто ~.

exit 0
split

Утилита разбивает файл на несколько частей. Обычно используется для разбиения больших файлов, чтобы их можно было записать на дискеты или передать по электронной почте по частям.

sum, cksum, md5sum

Эти утилиты предназначены для вычисления контрольных сумм. Контрольная сумма -- это некоторое число, вычисляемое исходя из содержимого файла, и служит для контроля целостности информации в файле. Сценарий может выполнять проверку контрольных сумм для того, чтобы убедиться, что файл не был изменен или поврежден. Для большей безопасности, рекомендуется использовать 128-битную сумму, генерируемую утилитой md5sum (message digest checksum).

bash$ cksum /boot/vmlinuz
1670054224 804083 /boot/vmlinuz


bash$ md5sum /boot/vmlinuz
0f43eccea8f09e0a0b2b5cf1dcf333ba  /boot/vmlinuz
        


Обратите внимание: утилита cksum выводит контрольную сумму и размер файла в байтах.

Пример 12-32. Проверка целостности файла

#!/bin/bash
# file-integrity.sh: Проверка целостности файлов в заданном каталоге

E_DIR_NOMATCH=70
E_BAD_DBFILE=71

dbfile=File_record.md5
# Файл для хранения контрольных сумм.


set_up_database ()
{
  echo ""$directory"" > "$dbfile"
  # Записать название каталога в первую строку файла.
  md5sum "$directory"/* >> "$dbfile"
  # Записать контрольные суммы md5 и имена файлов.
}

check_database ()
{
  local n=0
  local filename
  local checksum

  # ------------------------------------------- #
  #  Возможно эта проверка и не нужна,
  #+ но лучше перестраховаться сейчас, чем жалеть об этом потом.

  if [ ! -r "$dbfile" ]
  then
    echo "Не могу прочитать файл с контрольными суммами!"
    exit $E_BAD_DBFILE
  fi
  # ------------------------------------------- #

  while read record[n]
  do

    directory_checked="${record[0]}"
    if [ "$directory_checked" != "$directory" ]
    then
      echo "Имя каталога не совпадает с записаным в файле!"
      # Попытка использовать файл контрольных сумм для другого каталога.
      exit $E_DIR_NOMATCH
    fi

    if [ "$n" -gt 0 ]   # Не имя каталога.
    then
      filename[n]=$( echo ${record[$n]} | awk '{ print $2 }' )
      #  md5sum записывает в обратном порядке,
      #+ сначала контрольную сумму, затем имя файла.
      checksum[n]=$( md5sum "${filename[n]}" )

      if [ "${record[n]}" = "${checksum[n]}" ]
      then
        echo "Файл ${filename[n]} не был изменен."
      else
        echo "ОШИБКА КОНТРОЛЬНОЙ СУММЫ для файла ${filename[n]}!"
        # Файл был изменен со времени последней проверки.
      fi

    fi


    let "n+=1"
  done <"$dbfile"       # Чтение контрольных сумм из файла.

}

# =================================================== #
# main ()

if [ -z  "$1" ]
then
  directory="$PWD"      #  Если каталог не задан,
else                    #+ то используется текущий каталог.
  directory="$1"
fi

clear                   # Очистка экрана.

# ------------------------------------------------------------------ #
  if [ ! -r "$dbfile" ] # Необходимо создать файл с контрольными суммами?
  then
    echo "Создание файла с контрольными суммами, \""$directory"/"$dbfile"\"."; echo
    set_up_database
  fi
# ------------------------------------------------------------------ #

check_database          # Выполнить проверку.

echo

#  Вывод этого сценария можно перенаправить в файл,
#+ это особенно полезно при проверке большого количества файлов.

#  Более строгая проверка целостности файлов,
#+ может быть выполнена с помощью пакета "Tripwire",
#+ http://sourceforge.net/projects/tripwire/.

exit 0

Более творческий подход к использованию md5sum вы нйдете в Пример A-21.

shred

Надежное, с точки зрения безопасности, стирание файла, посредством предварительной, многократной записи в файл случайной информации, перед тем как удалить его. Эта команда имеет тот же эффект, что и Пример 12-45, но делает это более изящным и безопасным способом.

Является составной частью пакета GNU fileutils.

Caution

Имеется ряд технологий, с помощью которых все-таки возможно восстановить файлы, удаленные утилитой shred.

Кодирование и шифрование

uuencode

Эта утилита используется для кодирования двоичных файлов в символы ASCII, после такого кодирования файлы могут, с достаточной степенью безопасности, передаваться по сети, вкладываться в электронные письма и т.п..

uudecode

Утилита декодирования файлов, прошедших обработку утилитой uuencode.

Пример 12-33. Декодирование файлов

#!/bin/bash

lines=35        # 35 строк для заголовка (более чем достаточно).

for File in *   # Обход всех файлов в текущем каталоге...
do
  search1=`head -$lines $File | grep begin | wc -w`
  search2=`tail -$lines $File | grep end | wc -w`
  #  Закодированные файлы начинаются со слова "begin",
  #+ и заканчиваются словом "end".
  if [ "$search1" -gt 0 ]
  then
    if [ "$search2" -gt 0 ]
    then
      echo "декодируется файл - $File -"
      uudecode $File
    fi
  fi
done

#  Обратите внимание: если передать сценарию самого себя, для декодирования,
#+ то это введет его в заблуждение
#+ поскольку в тексте сценария встречаются слова "begin" и "end".

exit 0
Tip

При декодировании и выводе длинных текстовых сообщений из новостных групп Usenet, очень нелишним будет передать текст, по конвейеру, команде fold -s.

mimencode, mmencode

Утилиты mimencode и mmencode предназначены для обработки закодированных мультимедийных вложений в электронные письма. Хотя почтовые программы (такие как pine или kmail) имеют возможность автоматической обработки таких вложений, тем не менее эти утилиты позволяют обрабатывать вложения вручную, из командной строки или в пакетном режиме, из сценария на языке командной оболочки.

crypt

Одно время, это была стандартная, для Unix, утилита шифрования файлов. [2] Политически мотивированные, правительственные постановления ряда стран, напрямую запрещают экспорт программного обеспечения для шифрования, что, в результате, привело практически к полному исчезновению crypt из большинства Unix-систем (в том числе и Linux). К счастью, программистами было разработано множество вполне приличных альтернатив, и среди них cruft (см. Пример A-5).

Прочее

mktemp

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

PREFIX=filename
tempfile=`mktemp $PREFIX.XXXXXX`
#                        ^^^^^^ Необходимо по меньшей мере 6 заполнителей
echo "имя временного файла = $tempfile"
# имя временного файла = filename.QA2ZpY
#                 или нечто подобное...


make

Утилита для компиляции и сборки программ. Но может использоваться для выполнения любых других операций, основанных на анализе наличия изменений в исходных файлах.

Команда make использует в своей работе Makefile, который содержит перечень зависимостей и операций, которые необходимо выполнить для удовлетворения этих зависимостей.

install

Своего рода -- утилита копирования файлов, похожа на cp, но дополнительно позволяет изменять права доступа и атрибуты копируемых файлов. Напрямую эта команда практически не используется, чаще всего она встречается в Makefile (в разделе make install :). Она может использоваться в сценариях установки ПО.

dos2unix

Автор утилиты -- Benjamin Lin со-товарищи. Предназначена для преобразования текстовых файлов из формата DOS (в котором строки завершаются комбинацией символов CR-LF) в формат Unix (в котором строки завершаются одним символом LF) и обратно.

ptx

Команда ptx [targetfile] выводит a упорядоченный предметный указатель для targetfile, который можно обработать, по мере необходимости, какой либо утилитой форматирования, в конвейере.

more, less

Команды постраничного просмотра текстовых файлов или потоков на stdout. Могут использоваться в сценариях в качестве фильтров.

Notes

[1]

Команда tar czvf archive_name.tar.gz * включит в архив все скрытые файлы (имена которых начинаются с точки) из вложенных подкаталогов. Это недокументированная "особенность" GNU-версии tar.

[2]

Она реализует алгоритм симметричного блочного шифрования, в противоположность алгоритмам шифрования с "открытым ключом", из которых широко известен pgp.