# Почему?
Сравнение
diff, patch
Утилиты
sum, cksum, md5sum
shred
Кодирование и шифрование
diff: очень гибкая утилита сравнения файлов. Она выполняет построчное сравнение файлов. В отдельных случаях, таких как поиск по словарю, может оказаться полезной фильтрация файлов с помощью sort и uniq перед тем как отдать поток данных через конвейер утилите diff. diff file-1 file-2 -- выведет строки, имеющие отличия, указывая -- какому файлу, какая строка принадлежит.
С ключом --side-by-side, команда diff выведет сравниваемые файлы в две колонки, с указанием несовпадающих строк. Ключи -c и -u так же служат для облегчения интерпретации результатов работы diff.
Существует ряд интерфейсных оболочек для утилиты diff, среди них можно назвать: spiff, wdiff, xdiff и mgdiff.
В общем случае, 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?).
bash$ diff -r ~/notes1 ~/notes2
Only in /home/bozo/notes1: file02
Only in /home/bozo/notes1: file03
Only in /home/bozo/notes2: file04
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 лишь показывет номер строки и позицию в строке, где было встречено различие.
Пример 12-27. Пример сравнения двух файлов с помощью 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
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 от полного имени файла и выводит только путь к файлу.
Пример 12-28. Утилиты 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
Утилита разбивает файл на несколько частей. Обычно используется для разбиения больших файлов, чтобы их можно было записать на дискеты или передать по электронной почте по частям.
Эти утилиты предназначены для вычисления контрольных сумм. Контрольная сумма -- это некоторое число, вычисляемое исходя из содержимого файла, и служит для контроля целостности информации в файле. Сценарий может выполнять проверку контрольных сумм для того, чтобы убедиться, что файл не был изменен или поврежден. Для большей безопасности, рекомендуется использовать 128-битную сумму, генерируемую утилитой md5sum (message digest checksum).
bash$ cksum /boot/vmlinuz
1670054224 804083 /boot/vmlinuz
bash$ md5sum /boot/vmlinuz
0f43eccea8f09e0a0b2b5cf1dcf333ba /boot/vmlinuz
Обратите внимание: утилита cksum выводит контрольную сумму и размер файла в байтах.
Пример 12-29. Проверка целостности файла
#!/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.
Надежное, с точки зрения безопасности, стирание файла, посредством предварительной, многократной записи в файл случайной информации, перед тем как удалить его. Эта команда имеет тот же эффект, что и Пример 12-42, но делает это более изящным и безопасным способом.
Является составной частью пакета GNU fileutils.
uuencode
Эта утилита используется для кодирования двоичных файлов в символы ASCII, после такого кодирования файлы могут, с достаточной степенью безопасности, передаваться по сети, вкладываться в электронные письма и т.п..
uudecode
Утилита декодирования файлов, прошедших обработку утилитой uuencode.
Пример 12-30. Декодирование файлов
#!/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