sneeze of the baby, the shriek of the Gryphon, and all the other
queer noises, would change (she knew) to the confused clamour of
the busy farm-yard-while the lowing of the cattle in the distance
would take the place of the Mock Turtle’s heavy sobs.
Еще раз выполнить в нем поиск строки teacup.
$ zgrep teacup ragged.txt.Z
rattling teacups would change to tinkling sheep-bells, and the
При этом файл сохранится в сжатом состоянии, как показывает листинг 4.18.
Листинг 4.18.Вывод команды ls показывает, что имеется только один файл с таким именем, и это сжатый файл
$ ls −l ragged.txt*
-rw-r-r-··1 taylor··staff··443 Jul··7 16:07 ragged.txt.Z
Усовершенствование сценария
Самый большой недостаток сценария состоит в том, что, если прервать его работу на полпути, он может не успеть повторно сжать файл. Отличным усовершенствованием стало бы исправление этой проблемы с помощью команды trap и функции сжатия, выполняющей проверку на наличие ошибок.
№ 34. Гарантия максимальной степени сжатия файла
Как было отмечено в рецепте № 33, большинство реализаций Linux включает несколько утилит сжатия, но решать, какая из них наиболее эффективно сожмет конкретный файл, приходится пользователю. Однако пользователи обычно привыкают к одной программе, не подозревая, что другие утилиты дали бы лучшие результаты. Еще бо́льшую сумятицу вносит тот факт, что некоторые файлы лучше сжимаются с использованием одного алгоритма, а другие — с использованием другого, и нет никакой возможности выявить лучший вариант без прямых экспериментов.
Логичное решение проблемы — написать сценарий, который сожмет файл с применением каждого из инструментов и оставит наименьший файл как наилучший. Именно это делает сценарий bestcompress, представленный в листинге 4.19!
Листинг 4.19.Сценарий bestcompress
#!/bin/bash
# bestcompress — пытается сжать файл всеми доступными инструментами
#·· сжатия и сохраняет наименьший сжатый файл, сообщая результат
#·· пользователю. Если флаг −a не указан, bestcompress пропускает
#·· сжатые файлы, указанные в аргументах командной строки.
Z="compress"···· gz="gzip"····bz="bzip2"
Zout="/tmp/bestcompress.$$.Z"
gzout="/tmp/bestcompress.$$.gz"
bzout="/tmp/bestcompress.$$.bz"
skipcompressed=1
if ["$1" = "-a"]; then
··skipcompressed=0; shift
fi
if [$# −eq 0]; then
··echo "Usage: $0 [-a] file or files to optimally compress" >&2
··exit 1
fi
trap "/bin/rm −f $Zout $gzout $bzout" EXIT
for name in "$@"
do
··if [! -f "$name"]; then
····echo "$0: file $name not found. Skipped." >&2
····continue
··fi
··if ["$(echo $name | egrep '(\.Z$|\.gz$|\.bz2$)')"!= ""]; then
····if [$skipcompressed −eq 1]; then
······echo "Skipped file ${name}: It's already compressed."
······continue
····else
······echo "Warning: Trying to double-compress $name"
····fi
··fi
··# Запустить параллельное сжатие файла тремя инструментами.
··$Z < "$name" > $Zout &
··$gz < "$name" > $gzout &
··$bz < "$name" > $bzout &
··wait # ждать, пока все три инструмента завершат сжатие.
··# Выявить файл, сжатый лучше всех.
··smallest="$(ls −l "$name" $Zout $gzout $bzout | \
····awk '{print $5"="NR}' | sort −n | cut −d= −f2 | head -1)"
··case "$smallest" in
····1) echo "No space savings by compressing $name. Left as is."
········;;
····2) echo Best compression is with compress. File renamed ${name}.Z
········mv $Zout "${name}.Z"; rm −f "$name"
········;;
····3) echo Best compression is with gzip. File renamed ${name}.gz
········mv $gzout "${name}.gz"; rm −f "$name"
········;;
····4) echo Best compression is with bzip2. File renamed ${name}.bz2
········mv $bzout "${name}.bz2"; rm −f "$name"
··esac
done
exit 0
Самая интересная строка в сценарии —
. Команда ls в этой строке выводит размеры каждого файла (исходного и трех сжатых, в определенном порядке), команда awk выделяет размеры файлов, команда sort сортирует результаты в числовом порядке, и в конце остается номер строки в выводе ls с наименьшим файлом. Если все сжатые версии получились больше оригинала, результат будет равен 1, и на экране появится соответствующее сообщение
. Иначе число покажет, какая из утилит — compress, gzip или bzip2 — лучше справилась с задачей. Затем остается только переместить соответствующий файл в текущий каталог и удалить оригинал.
Читать дальше