Официальная возможность получить лицензионный софт бесплатно.
Giveaway of the Day
Это не реклама!

Щелкните для получения прогноза по Биробиджану


среда, 13 декабря 2017 г.

bash: массовое уменьшение фото в каталоге

Есть в нашем мире долбодятлы. Чем они отличаются от обычных людей? Например тем, что принципиально не способны выбирать для работы правильный инструмент. Например, они пробивают перфоратором с метровым буром деревянную доску-десятку. Или забивают в нее гвозди кувалдой, которой только что вгоняли костыли в шпалы. Или будут есть китайскими палочками не только лапшу и салаты, но и яичницу-глазунью или суп. Только потому, что ухватив инструмент, они не хотят брать другой. Или не знают, что он есть. Но чаще им просто лень потратить несколько секунд для того чтобы взять более подходящий инструмент.
Как известно, каждый дрочит как хочет, и я не собираюсь обсуждать любителей забивать гвозди микроскопом. До тех пор, пока это не мешает работе моих файловых серверов. Нет, ни любители палочек, ни любители перфораторов мне не мешают. А вот любители размещать на серверах фото в огромном разрешении - эти мешают. И они тоже относятся к породе долбодятлов.
Например, важный снимок - ход строительства одного из наших объектов. Снято на мультимегапиксельную говномыльницу. Размер снимка 5 мегов. Сюжет: кусок кирпичной стены и тропинка вдоль нее. Всё. Никаких мелких или существенных деталей нет. Просто оператору было лень выбрать режим съемки 3 или 2Мпикс, он как выставил при покупке 12Мпикс, так и щелкает всё подряд.
Возникает вопрос: как утоптать всё это в более-менее скромный объем, если пациент принципиально не желает пользоваться настройками своего фотоаппарата или программой для уменьшения геометрических размеров фото? Очень просто: уменьшить эти снимки самостоятельно. В этом нам поможет convert из пакета ImageMagick.

Находим каталог с большим количеством неоправданно жирных фото.

find -iname *.jpg -size +3M -exec ls -l "{}" \; >large-photos

Просматриваем этот файл. Я делаю это вручную, но только потому что, мне лень еще полнее автоматизировать процесс, но может когда-то и доведу его до полного солипсизма полного автоматизма. Находим каталог-жертву и делаем ему матумбу (записано в одну строку, но внутри скрипта можно размазать и на несколько:

for a in *;do fn="${a%.*}";fe="${a##*.}";convert $a -resize 50% ${fn}s\.$fe;chmod ${fn}s\.$fe --reference=$a;chown ${fn}s\.$fe --reference=$a;touch ${fn}s\.$fe --reference=$a;done

Итак, по порядку:

for a in * - список файлов текущего каталога
fn - имя файла без расширения, выделяется с помощью штатных возможностей bash. (в Advanced Bash Scriptuing Guide глава 10. Manipulating Variables, раздел 10.1. Manipulating Strings, подраздел Substring Removal)
fe - расширение файла без имени, выделяется аналогично fn. Две этих раздельных части имени пригодятся позже
convert ИМЯ_ИСХОДНОГО_ФАЙЛА -resize 50% - уменьшает геометрический размер изображения в 4 раза (на 50% по каждой стороне).
${fn}s\.$fe - ...и записывает его файл с именем вида fns.fne, где "s" - это дописываемый к исходному имени суффикс, сокращение от слова "scaled" (масштабированный). Чтобы не возиться с определением места, куда вставить эту "s", я и использую отдельно взятые имя и расширение. На всякий случай экранируем точку, отделяющую имя от расширения.
chmod, chown и touch - заметаем следы, назначая свежесозданному мини-рисунку все атрибуты его большего предка: владельца, группу, права доступа и времена. У всех трёх команд набор параметров одинаковый: имя файла, которым манипулируем и после ключа --reference - имя файла, у которого берем "эталонные" значения. В моем случае это исходный файл.

Например, есть файл DSC01234.jPg. Соответственно:
fn=DSC01234
fe=jPg
уменьшенная копия будет записана в файл DSC01234s.jPg, и получит все атрибуты оригинала.

Я ориентировался на имена файлов, создаваемых нормальными камерами, то есть, не содержащие пробелов и спецсимволов. Возможно, для большей универсальности понадобятся кавычки.
Почему $fe используется сама по себе, а $fn - только в форме ${fn}? Потому что после $fn идет суффикс "s", который в противном случае будет считаться частью имени несуществующей переменной $fns.
Разумеется, для красоты можно ${fn}s\.$fe запихать в переменную, и, возможно, так и придется сделать при обработке файлов с вычурными именами, но пока для меня это не актуально.