Автоматизация jpegtran | FreeBSD
Решил заняться оптимизацией изображений на вебсервере – jpegtran и подобные утилиты позволяют уменьшить размер изображений без потери качества – удаляют мета информацию и т.д.
Вызов такой:
jpegtran -copy none -optimize -perfect -outfile outfile.jpeg sourcefile.jpeg
или
jpegtran -copy none -optimize -perfect source.jpg > dest.jpg
Все хорошо, но для оптимизации работы хорошо бы написать скрипт для автоматизации работы – указать целевую папку и запланировать в крон.
Пришлось немного поупражняться в «программировании» в шелл.
Основа для скрипта нашлась в сети, я лишь внес небольшие изменения и оформил функцией. Ищем файлы с разрешением jpg, jpeg, png и обрабатываем копируя во временный файл с последующей заменой исходного файла.
tran() {
echo "Start OPTIMIZING...."
for file
in `find $DIR -iname "*.jpg" -or -iname "*.png" -or -iname "*.jpeg"`;
do
ext=${file##*.}
if [ -n "$ext" ]; then
if [ "$ext" = "jpg" ]; then
echo "optimizing ${file} as jpeg file with jpegtran"
jpegtran -copy none -optimize -perfect -outfile temp_file.jpg $file
mv -f temp_file.jpg $file;
fi
if [ "$ext" = "jpeg" ]; then
echo "optimizing ${file} as jpeg file with jpegtran"
jpegtran -copy none -optimize -perfect -outfile temp_file.jpeg $file
mv -f temp_file.jpeg $file;
fi
if [ "$ext" = "png" ]; then
echo "optimizing ${file} as png file with pngcrush"
pngcrush -rem alla -reduce -brute "$file" temp_file.png;
mv -f temp_file.png $file;
fi
fi
done;
echo "OPTIMIZE IS DONE!";
echo "You can find your files before optimization in $DIR.old"
}
В самом начале скрипта обьявляем переменные:
DIR=$1;
DIR=`echo $1 |sed -e 's,\(.\)/$,\1,'`
DIR – берется из строки запроса: $0 – это всегда имя скрипта в строке, $1 – это то что мы передаем скрипту в качестве аргумента:
./script.sh argument
У нас вызов будет такой (в качестве аргумента передаем имя папки в кторой лежат файлы для обработки):
./script.sh /dir_to_proceed
Строка DIR=`echo $1 |sed -e 's,\(.\)/$,\1,'`
удаляет слеши в конце пути котрый мы указали – целевая папка должна указываться без слеша в конце.
Бэкапим целевую папку (можно указать временную метку вместо .old):
back() {
mkdir "$DIR.old";
for i in `ls $DIR`;
do
cp $DIR/$i $DIR.old;
done;
echo "Your files copied to $DIR.old...."
}
Теперь нужно провести проверку того что мы передали скрипту переменную – указали какую папку обработать. Пишем цикл с условием – если переменная $DIR не пустая ( -z) значит выполняем функции бэкапа и обработки, если переменную скрипту не передали – выходим с ошибкой (exit 1):
dojob() {
if [ -z "$DIR" ]
then
echo "Script usage: ./tran.sh /dirname"
exit 1
else
back
tran
fi
}
Теперь осталось вызвать функцию:
echo "Script is starting...."
dojob
echo "Script job finished"
exit 0
Теперь все собираем вместе:
#!/bin/sh.
DIR=$1;
DIR=`echo $1 |sed -e 's,\(.\)/$,\1,'`
back() {
mkdir "$DIR.old";
for i in `ls $DIR`;
do
cp $DIR/$i $DIR.old;
done;
echo "Your files copied to $DIR.old...."
}
tran() {
echo "Start OPTIMIZING...."
for file
in `find $DIR -iname "*.jpg" -or -iname "*.png" -or -iname "*.jpeg"`;
do
ext=${file##*.}
if [ -n "$ext" ]; then
if [ "$ext" = "jpg" ]; then
echo "optimizing ${file} as jpeg file with jpegtran"
jpegtran -copy none -optimize -perfect -outfile temp_file.jpg $file
mv -f temp_file.jpg $file;
fi
if [ "$ext" = "jpeg" ]; then
echo "optimizing ${file} as jpeg file with jpegtran"
jpegtran -copy none -optimize -perfect -outfile temp_file.jpeg $file
mv -f temp_file.jpeg $file;
fi
if [ "$ext" = "png" ]; then
echo "optimizing ${file} as png file with pngcrush"
pngcrush -rem alla -reduce -brute "$file" temp_file.png;
mv -f temp_file.png $file;
fi
fi
done;
echo "OPTIMIZE IS DONE!";
echo "You can find your files before optimization in $DIR.old"
}
dojob() {
if [ -z "$DIR" ]
then
echo "Script usage: ./tran.sh /dirname"
exit 1
else
back
tran
fi
}
echo "Script is starting...."
dojob
echo "Script job finished"
exit 0
Не забываем установить соответствующие пакеты: jpegtran и pngcrush!
Осталось только научить скрипт обрабатывать папки с рекурсией, протестировать и добавить в крон…