LXF148:tut5
2sash-kan (обсуждение | вклад) (Новая страница: «==Команды: GNU/Linux и смекалка== :'''Тихон Тарнавский''' рассказывает, как средствами командной…») |
Текущая версия на 20:16, 21 июля 2014
|
|
|
Содержание |
[править] Команды: GNU/Linux и смекалка
- Тихон Тарнавский рассказывает, как средствами командной строки
навести порядок в коллекции фотографий.
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
На этот раз мы займемся картинками. Нет, обрабатывать изображения я не предлагаю. Хотя для этого тоже есть утилиты командной строки, но работа с ними весьма специфична и, говоря прямо, к навыкам решения более общих задач в командной строке имеет очень мало отношения. Работать будем не с отдельной картинкой, а с коллекцией картинок. Наверное, почти у каждого на компьютере есть такая коллекция, собранная из многих разных источников: с сайтов в интернете, с фотоаппарата и так далее. Обычно она все время пополняется, и хотя бы изредка ее приходится упорядочивать. Конечно, распределить фотографии по тематике часто только вручную и можно, но есть и другие, более механические задачи. Например, если вы хотя бы раз сохраняли целиком web-страницы с картинками или загружали к себе на компьютер целые сайты, то, помимо нужных вам изображений, получили огромное количество других файлов. Потом эти файлы и под руками путаются, и в то же время обойти многочисленные каталоги и все почистить – работа нудная и заниматься ею никогда не хочется. Думаю, идея уже ясна: возложить эту нудную работу на наших «слуг проворных, удалых» – командную оболочку и связанные ею отдельные команды и программы.
Для начала поставим задачу в целом. Нам нужно избавиться от разнообразных вспомогательных файлов, вроде самих web-страниц, скриптов, стилей и тому подобное – то есть от всего, кроме изображений. Кроме того, нужно вычистить все оформительские и рекламные элементы; а это обычно изображения небольшого размера (по крайней мере, по одной из сторон). Тогда и должно остаться только требуемое нам.
[править] Отделяем зерна от плевел
Начнем с удаления побочных файлов. Первым делом нужно найти все обычные файлы в заданном каталоге (как это сделать, мы уже рассматривали: см. статью в LXF145). Затем отсеем все прочие файлы кроме картинок. Как мы можем отличить «прочий файл» от картинки? По расширению? Ответ неверный. Во-первых, человек не обязан знать все расширения, которые бывают у картинок. Во-вторых, имя файла может быть не совсем правильным, а поскольку все неподходящие файлы мы будем удалять, досадно будет ошибиться. А уж проверять содержимое файла на то, что это действительно картинка, человек не только не может, но и не должен – тогда теряется весь смысл затеи. А то, что не должен делать человек, за человека должна сделать программа. И в GNU/Linux есть специальная программа, выдающая тип файла по его содержимому. Называется она более чем очевидно: file. Проверим, как выглядит ее вывод, в любом каталоге с картинками (здесь * – это специальный шаблон, который раскрывается командной оболочкой в полный список файлов в текущем каталоге):
$ file * 1_002.jpg: JPEG image data, JFIF standard 1.01 1.jpg: JPEG image data, EXIF standard, baseline, precision 0, 4360x902 11.js: HTML document text 12.gif: GIF image data, version 89a, 167 x 9 14.js: HTML document text 2_002.jpg: JPEG image data, JFIF standard 1.01 2.jpg: JPEG image data, EXIF standard, baseline, precision 0, 4360x902 3_002.jpg: JPEG image data, JFIF standard 1.01 3.gif: GIF image data, version 89a, 56 x 57 3.jpg: JPEG image data, EXIF standard, baseline, precision 0, 4360x902 4_002.jpg: JPEG image data, JFIF standard 1.01 4.jpg: JPEG image data, EXIF standard, baseline, precision 0, 4360x902 common.js: ISO-8859 text, with CRLF line terminators full.png: PNG image data, 2000 x 1000, 8-bit colormap, non-interlaced help.css: ASCII text, with CRLF line terminators main1.css: ISO-8859 assembler program text, with CRLF line terminators page_btn.gif: GIF image data, version 89a, 31 x 31
Как видите, каждая строка с файлом изображения содержит фразу “image data”. У команды file есть и немного другой режим работы – в нем она выдает не текстовые описания типов файлов, а так называемые «mime-типы», то есть строки вида “text/html” или “image/gif”. Казалось бы, логичнее использовать именно его и отбирать файлы по строке “image” в описании. Но увы, к тому же mime-типу image относится, к примеру, и подтип image/djvu, который картинкой в интересующем нас сейчас понимании не является. А вот его описание в текстовом виде выглядит как “DjVu multiple page document”, то есть строки “image data” не содержит. Так что будем обрабатывать текстовые описания. С командой grep, отфильтровывающей нужные строки текста, мы уже знакомы. Но раньше нам нужно было оставлять строки, содержащие заданный текст, а сейчас – наоборот: те, в которых заданного текста нет. В man grep нетрудно найти нужную опцию – v. Значит, передадим список найденных файлов команде file, а полученные описания отфильтруем командой grep -v:
find -type f -print0 | xargs -0 file | grep -v “ image data”
Из полученных строк нужно вычленить имена файлов. На первый взгляд это можно сделать командой cut, использовав в качестве разделителя полей двоеточие; на самом деле не все так просто. Ведь если двоеточие встретится в имени файла, то мы получим лишь часть имени до этого двоеточия. Нужно оставить все поля, кроме последнего. Но как это сделать, не зная их количества? Самый очевидный способ – перевернуть строку, затем выделить все поля, кроме первого, затем перевернуть обратно. Команда cut позволяет задавать диапазоны полей (два номера через дефис); в том числе и незамкнутые на конце (номер после дефиса опускается), что означает «отсюда и до конца строки». Осталось только перевернуть строку. А с этим нам поможет команда rev (от англ. reverse – переворачивать) из пакета util-linux. Этот пакет скорее всего уже установлен в вашей системе, так что можно нужную команду сразу использовать. Используется она очень просто: не принимает вообще никаких опций и только то и делает, что переставляет символы в каждой строке в обратном порядке.
find -type f -print0 | xargs -0 file | grep -v “ image data” | rev | cut -d : -f 2- | rev
Прежде чем двигаться дальше, дам небольшое предупреждение. Следующим шагом нам нужно удалить найденные файлы. И вы как владелец файлов заинтересованы проследить за тем, чтобы не удалить ничего лишнего. В данном случае вероятность такого очень мала, но привычку лучше выработать сразу: в будущем вы скорее всего не раз этому порадуетесь. Застраховаться от потери можно двумя способами.
Первый, более очевидный, подходит, когда вы хотите проверить, что будет удалено: временно вставить в полученный конвейер вместо команды удаления команду вывода списка файлов – ls.
Второй удобен для просмотра того, что останется: предварительно скопировать обрабатываемый каталог. Не бойтесь, что это будет долго: копировать мы будем тоже в стиле unix-way. В Unix-совместимых системах содержимое файла и его имя можно рассматривать как два отдельных, хотя и взаимосвязанных объекта. Имя всего лишь ссылается на содержимое, а таких ссылок может быть несколько. То есть один и тот же файл может иметь одновременно несколько имен. Называются эти ссылки-имена жесткими ссылками [hard links] – кроме них, есть еще ссылки символические [symbolic links], которые мы скорее всего тоже будем использовать в следующих статьях. Само содержимое файла считается удаленным только после того, как на него не осталось ни одной жесткой ссылки. Понятно, чем жесткие ссылки удобны в нашем случае: на создание дополнительной ссылки по сравнению с копированием содержимого файла, можно сказать, вообще не тратится время. Думаете, опять придется что-то искать и передавать куда-то по конвейеру? Ничего подобного, все уже предусмотрено: у команды копирования cp есть ключ l, который заставляет ее вместо копирования содержимого создавать на него дополнительную жесткую ссылку. Достаточно скомбинировать этот ключ с ключом r, отвечающим за рекурсивное копирование каталогов со всеми вложенными подкаталогами и файлами – и вы получите во временном каталоге полный дубликат всех подкаталогов и жестких ссылок (имен файлов) без копирования самого содержимого файлов (только убедитесь предварительно, что каталога или файла с таким же именем еще нет в месте назначения):
cp -rl ~/media/images ~/tmp
Теперь можете экспериментировать с копией сколько угодно, а если что-то пойдет не так, выполнить эту команду заново. Подстелив соломки, можем смело «прыгать» – добавлять команду rm, удаляющую файлы:
find -type f -print0 | xargs -0 file | grep -v “ image data” | rev | cut -d : -f 2- | rev | xargs rm
[править] Ловись, картинка большая
Теперь, когда все, кроме картинок, мы удалили, осталось отобрать их по размеру. Здесь уже команда file не справится, так как для некоторых типов изображений она размер в точках не выдает. Но теперь мы уже знаем, что все оставшиеся файлы – картинки, поэтому логично будет обратиться к более специализированной программе. Пакет таких специализированных программ, работающих с изображениями из командной строки, называется imagemagic. Он состоит из одиннадцати программ, каждая из которых выполняет свой узкий набор задач (краткое описание можно найти в man ImageMagic). Нам из них понадобится программа под названием identify. В отличие от других программ из этого пакета, она никак не изменяет сами файлы изображений, а только выводит различную техническую информацию о них. По умолчанию, без опций identify выводит имя файла, тип изображения (который может не совпадать с «расширением»), разрешение и еще несколько параметров, которые нас сейчас не интересуют (рис. 2). Как видно на снимке экрана, в конце было выдано некое сообщение об ошибке, поэтому при добавлении identify в конвейер нужно не забыть перенаправить поток ошибок «в никуда».
Из вывода identify нам в первую очередь надо вычленить разрешение картинки. Тут нам на помощь снова придет команда grep: она умеет отфильтровывать не только целые строки, но и части строк. Для этого следует задать опцию o и специальный «шаблон», под который должна подойти нужная часть строки. На самом деле называть это шаблоном не совсем верно – лучше не смешивать с шаблоном имен файлов в командной оболочке (потому я и взял это слово в кавычки); правильное название – регулярное выражение [regular expression]. Регулярные выражения – очень гибкий инструмент, но именно поэтому не слишком простой, поэтому изучать их детально мы пока не будем. Упомяну только два обозначения, которые нам пригодятся, чтобы вычленить интересующую нас часть строки. А интересует нас разрешение, которое записано как «число, буква x, число» и окружено пробелами.
Квадратные скобки со списком символов внутри означают любой из перечисленных символов. Причем символы, идущие подряд, можно обозначать как диапазон «начало-конец». То есть понятие «любая цифра» переводится в регулярные выражения так: [0-9]. А число – это последовательность цифр произвольной длины. Поэтому следующий элемент регулярного выражения, который нам понадобится, это звездочка: она означает повторение того, что записано перед ней, любое количество раз (начиная от нуля). Значит, понятие «любое число» на языке регулярных выражений выглядит так: [0-9]*. А полностью искомое запишется так: ' [0-9]*x[0-9]* ' (рис. 3).
Правильнее всего будет отсеивать картинки не по какому-то одному из размеров, а по минимальному. Ведь среди элементов оформления web-страниц бывают и узкие полосы довольно большой длины. Поэтому напишем маленький вспомогательный скрипт, вычленяющий два числа из заданной строки и выводящий меньшее из них. Глядишь, и в будущем когда-нибудь пригодится! Назовем его ~/bin/min (не забудьте добавить к файлу право на исполнение). Вырезать числа из строки будем все тем же grep -o; а брать саму строку – из параметров командной строки. И сохранить найденные в строке числа тоже будет удобнее всего на месте параметров командной строки. Делается это командой set.
#!/bin/bash set $(grep -o '[0-9]*')
Возможно, вас смутило, что команде grep ничего не передано на вход. Тут используется еще одна замечательная возможность командной оболочки: в этом случае первая команда в скрипте будет обрабатывать стандартный ввод скрипта, то есть сам скрипт можно будет использовать в конвейерах. Если в этом вводе встретится несколько чисел, то grep -o выведет их последовательно. А с помощью команды set они сохранятся в уже знакомых нам «переменных» $1, $2 и так далее. Впрочем, то, что далее, нас не интересует, так как сравнивать мы будем только первые два числа. Для сравнения используем не менее знакомую команду [(test) с параметром -lt (less than – меньше, чем). Почему условие «меньше, чем» записано буквами, а не привычным всем значком <? Да потому, что этот значок в командной оболочке уже задействован для перенаправления ввода.
#!/bin/bash set $(grep -o '[0-9]*') if [ “$1” -lt “$2” ]; then echo $1 else echo $2 fi
Теперь нам нужно снова искать все файлы и обрабатывать найденное построчно. Для этого передадим вывод find циклу while [пока] с командой read [читать] в качестве условия. Этот цикл повторяется до тех пор, пока не нарушено условие. А команда read читает одну строку, сохраняет ее в заданной переменной, а если читать больше нечего, завершается с ошибкой. Так что while read – это и есть построчная обработка ввода, пока он не закончится.
find -type f | while read f; do...
Поскольку найденные файлы мы будем удалять, если они меньше какого-то заданного размера, то этот размер стоит подобрать достаточно точно в зависимости от ваших картинок, а не наугад. Для этого отсортируем все картинки по меньшему из двух размеров (вертикального и горизонтального) и передадим программе просмотра, чтобы быстро пробежаться по списку и найти нужную грань. Первым делом для каждого файла выведем тот самый минимальный размер и имя файла:
find -type f | while read f; do echo $(identify “$f” 2>/dev/null | grep -o ' [0-9]*x[0-9]* ' | min) $f done
Теперь отсортируем полученный список числовой сортировкой и удалим само число (первое отделенное пробелом поле) командой cut, оставив только имя файла:
find -type f | while read f; do echo $(identify “$f” 2>/dev/null | grep -o ' [0-9]*x[0-9]* ' | min) $f done | sort -n | cut -d ' ' -f 2-
Наконец, передадим отсортированный список файлов программе просмотра. Я рекомендую для просмотра использовать pqiv (pretty quick image viewer – очень быстрая смотрелка картинок), она в этом случае очень хорошо подходит: во-первых, действительно быстрая; во-вторых, позволяет проматывать картинки не только по одной (клавишами Space/BackSpace), но и по 10 (PageUp/PageDn); и в-третьих, может отображать информацию о файле, включая разрешение, прямо во время просмотра. Запустим ее в полноэкранном режиме и найдем нужную «грань»:
pqiv -f $(find -type f | while read f; do
echo $(identify “$f” 2>/dev/null | grep -o ' [0-9]*x[0-9]* ' | min) $f;
done | sort -n | cut -d ' ' -f 2-)
У меня эта грань получилась равна 220 точкам – ниже нее попали не только оформительские элементы сайтов, но и все «картинки предпросмотра». Найдя нужное число по своим файлам, остается немного модифицировать тот же цикл, добавив в него сравнение меньшего из размеров картинки с найденным числом и удаление файла при выполнении условия:
find -type f | while read f; do [ “$(identify “$f” 2>/dev/null | grep -o ' [0-9]*x[0-9]* ' | min)” -lt 220 ] && rm “$f” done Или – в одну строку: find -type f | while read f; do [ “$(identify “$f” 2>/dev/null | grep -o ' [0-9]*x[0-9]* ' | min)” -lt 220 ] && rm “$f”; done
[править] А по мне, они одинаковые
В достаточно большой коллекции вполне могут встретиться одинаковые картинки. Это могут быть либо полностью идентичные файлы, либо разные варианты одного изображения – например, в разном разрешении или в разных форматах. Хорошо бы от таких дубликатов коллекцию тоже почистить. Здесь уже никаких настоящих юниксовых приемов не будет – просто дополним уже сделанное еще двумя отдельными узкоспециализированными программами. Начнем с поиска совершенно одинаковых файлов. Это замечательно делает программа fdupes (find duplicates – находить дубликаты). Работает она очень быстро, так как сравнивает сначала по размеру, затем (только при совпадении размеров) по контрольной сумме, и уже лишь при совпадении контрольных сумм сверяет содержимое побайтово. Конечно, при росте количества файлов время все равно растет в геометрической прогрессии, так что если у вас очень большая коллекция, придется немного подождать. У программы достаточно много опций, позволяющих гибко настроить как сам поиск, так и поведение при нахождении дубликатов.
Рассмотрим три варианта. В случае совершенно неупорядоченной коллекции мы будем удалять все дубликаты, оставляя только один экземпляр каждого файла: ведь в этом случае нам неважно, какой именно останется. В случае полностью упорядоченной коллекции будем заменять дубликаты жесткими ссылками на один и тот же файл: здесь, напротив, все экземпляры могут быть важны (например, находиться в разных тематических каталогах); и все они останутся, а место освободится. А в случае частично упорядоченной коллекции наперед неизвестно, что делать с файлами, поэтому будем спрашивать об этом человека, предлагая для каждой группы варианты: удалить все одинаковые файлы, кроме одного выбранного, либо пропустить группу, ничего не удаляя. Все это делается всего лишь опциями самой программы fdupes:
- fdupes -rdN .
- fdupes -rL .
- fdupes -rd .
Опция r отвечает за рекурсивную обработку всех подкаталогов и файлов в указанном месте (а указали мы точку, т. е. текущий каталог). Опция d, упомянутая сама по себе, приводит к «интерактивной» работе, запрашивая человека о каждой группе дубликатов. L заменяет копии ссылками. А N указывает, что удалять нужно в каждой группе все файлы, кроме первого, безо всяких запросов.
С одинаковыми файлами закончили, а второй случай, казалось бы, посложнее: тут уже надо найти не в точности совпадающие файлы, а «похожие» картинки. Но и такой поиск тоже можно осуществить одной-единственной программой, именно для этого и предназначенной: findimagedupes (находить дубликаты изображений). Она анализирует состав картинок и находит похожие с виду. Эта задача гораздо сложнее предыдущей, работает программа ощутимо медленнее, чем fdupes; поэтому и стоило от полностью одинаковых файлов избавиться заранее. Она тоже довольно гибко управляется, хотя подход к управлению использует несколько другой – большей частью через дополнительные скрипты. Но с похожими картинками все равно рискованно что-либо делать в полностью автоматическом режиме. Даже разрешение – не показатель, так как качество изображения зависит не только от него, да еще и субъективный фактор оценки нельзя сбрасывать со счетов. Кроме того, могут попасться не только разные варианты одной и той же картинки (даже по-разному обработанной), но и несвязанные похожие изображения: например, соседние фотоснимки из одной серии, с разницей в несколько секунд или минут. Поэтому на этот раз мы только подготовим список таких похожих картинок для дальнейшей обработки вручную. Наиболее удобный способ такой обработки – в программе просмотра картинок, умеющей работать с коллекциями (а не только с каталогами) и позволяющей в интерактивном режиме как сделать что-то с самими файлами (например, удалить), так и просто вычеркнуть их из коллекции. Здесь тоже ничего дополнительно делать не придется: findimagedupes умеет генерировать файл «коллекции» для одной такой программы (по сути, это просто список полных путей к файлам, только специально оформленный). Эта программа недавно была переименована в geeqie, а раньше называлась gqview (собственно, в man findimagedupes она и упоминается под старым названием). Так что для формирования коллекции похожих картинок и последующей ее ручной обработки достаточно дать две команды:
findimagedupes -R -c список.gqv . && geeqie список.gqv
Опция R опять-таки означает рекурсивный поиск (как и r у fdupes), а c задает имя файла коллекции.
И последний штрих. После всех этих удалений файлов могли остаться пустые каталоги. Их тоже хорошо бы подчистить. Здесь опять ничего комбинировать не нужно, достаточно одной только команды find. У нее есть опции empty [пустой] и delete [удалить]. Объединяем их с поиском каталогов (тип d, от слова directory) – и готово:
find -type d -empty -delete
Черновая работа по наведению порядка в коллекции выполнена. Все лишнее удалено, и место на диске освобождено. Теперь можно перейти к оценке художественной ценности картинок, но в этом ни одна программа помочь не может... пока не может.