Используйте mogrify для изменения размера больших файлов при игнорировании небольших

Я выполняю следующую команду:

mogrify -resize '400x400>' *.png 

Обратите внимание на «>». Предположительно, он будет игнорировать файлы меньшего размера, но, хотя он не изменяет их размер, он их редактирует (дата изменения и размер файла изменяются).

Есть ли способ сделать это на самом деле просто оставить небольшие файлы в одиночку? Я бы хотел избежать нескольких тысяч ненужных операций записи.

  • Найти файлы с 32 символами в рекурсивно в каталоге и применить команду
  • Прокручивайте файлы и конвертируйте BMP-файлы в JPG
  • Как использовать mogrify convert только в файлах с определенной датой создания?
  • Как создать временное видео из неподвижных изображений с определенным временем между каждым изображением?
  • 6 Solutions collect form web for “Используйте mogrify для изменения размера больших файлов при игнорировании небольших”

    Я думаю, что mogrify систематически перезаписывает файл, поэтому ваша единственная надежда состоит в том, чтобы сначала отфильтровать список, как было предложено jippie . Вот как вы можете это сделать (непроверенный): распечатать список файлов изображений с указанием размера, сохранить только имена, связанный размер которых находится в пределах диапазона, и обработать этот список.

     identify -format '%w %h %i\n' ./*.png | awk '$1 > 400 || $2 > 400 {sub(/^[^ ]* [^ ]* /, ""); print}' | tr '\n' '\0' | xargs -0 mogrify -resize '400x400' 

    Объяснение скрипта:

    • Для каждого файла напечатайте строку с шириной, пространством, высотой, пространством и именем файла. В зависимости от вашей версии identify \n чтобы добавить окончательную новую строку, может потребоваться (ImageMagick 6.6.0) или избыточно, но безвредно (GraphicsMagick 1.1.11).
    • ( awk ) В каждой строке, если ширина ( $1 ) и высота ( $2 ) соответствуют требуемым условиям, тогда:
      • Удалите весь текст со второго символа пробела. Это уменьшает ширину и высоту.
      • Распечатайте остатки строки, которая является именем файла.
    • Замените символы новой строки на нулевые символы.
    • Вызовите xargs -0 для выполнения команды mogrify для имен файлов. (Мы не можем использовать простые xargs потому что он не может обрабатывать входные данные, содержащие пробелы или \'" .»).

    Имена файлов могут содержать любой символ, кроме строк новой строки.

    Я столкнулся с той же проблемой, которую вы описали. Вот мое решение:

     #!/bin/bash files=*.jpg minimumWidth=640 minimumHeight=640 for f in $files do imageWidth=$(identify -format "%w" "$f") imageHeight=$(identify -format "%h" "$f") if [ "$imageWidth" -gt "$minimumWidth" ] || [ "$imageHeight" -gt "$minimumHeight" ]; then mogrify -resize ''"$minimumWidth"x"$minimumHeight"'' $f fi done 

    Я тестировал его на нескольких изображениях JPEG на виртуализированной машине CentOS 6.5. Сценарий изменил только размер и сжал изображения, ширина или высота которых превышала 640 пикселей. Это заставило его работать с изображениями размером 800 x 600 (пейзаж, изменение размера до 640 x 480) и размеры, такие как 600 x 800 (портрет, изменение размера до 480 x 640).

    PS: примечание о параметре 400x400 : mogrify будет обрабатывать файл, даже если его размеры равны или меньше 400×400, но будет изменять размер только в том случае, если его размеры больше 400×400. Вот почему меняются время и размер модификации файлов (в моем случае mogrify сделал эти файлы даже больше, чем они были).

    Как использовать идентификатор, чтобы найти размер вашего изображения и решить из небольшого скрипта, если вы хотите его отредактировать или нет:

     identify -format "width=%w heigth=%h" bootchart.png width=3853 heigth=10092 

    Не следует слишком сложно редактировать выходной формат для использования в простом скрипте.

    Вы также можете использовать оператор fx для фильтрации изображений по высоте / ширине, например

     identify -format '%[fx:(h>400 && w>400)]\n' image.png 

    будет выводиться 1 если изображение больше 400x400 и 0 если оно равно или меньше 400x400


    Предполагая, что имена здоровых файлов (без новых строк / пробелов / вкладок и т. Д.) Вы можете использовать identify для печати имен изображений, которым предшествует либо 1: либо 0: обрабатывать выходные строки удаления, начинающиеся с 0: и удаление ведущего 1: на остальной части строки, поэтому остаются только имена файлов, по одному на строку, а затем mogrify ... @- этот список для mogrify ... @- ( синтаксис @ был добавлен в imagemagick v6.5.2 ):

     identify -format '%[fx:(h>400 && w>400)]:%i\n' ./*.png | \ sed '/^1:/!d;//s///' | mogrify -resize '400x400' -- @- 

    В противном случае с помощью find вы можете печатать только файлы размером> 400×400, а затем передавать результат на xargs + mogrify (он менее эффективен, так как он запускает оболочку для каждого файла, но должен работать со всеми типами имен файлов):

     find . -maxdepth 1 -type f -name '*.png' -exec sh -c \ 'identify -format "%[fx:(h>400 && w>400)]\n" "$0" | grep -q 1' {} \; -print0 \ | xargs -0 mogrify -resize '400x400' 

    Если вы пользователь zsh см. Также этот ответ .

    Я использую такой PHP-скрипт, он использует ImageMagick:

     <?php $dir = "."; $exts = array('jpg', 'jpeg', 'png', 'gif'); $max_size = is_numeric($argv[1]) ? $argv[1] : 3000; $morgify = "mogrify -verbose -scale \"${max_size}x${max_size}>\" -quality 85"; $identify = "identify -format \"%wx%h\""; $dh = opendir($dir); while (($file = readdir($dh)) !== false) { $path = "$dir/$file"; // skip no images $dot = strrpos($file, '.'); $ext = strtolower(substr($file, $dot + 1)); if (!in_array($ext, $exts)) continue; // large size? $size = exec("$identify \"$path\""); list($width, $height) = explode('x', trim($size)); if (max($width, $height) > $max_size) { // scale! print "scale $file ${width}x${height}"; exec("$morgify \"$path\""); print "\n"; } } closedir($dh); ?> 

    Он масштабирует все изображения в текущем каталоге размером более 3000 на некотором краю.

    Команда запуска: php scale.php ИЛИ php scale.php 2000

    Вот мой подход к этому, включая идеи от @ArionKrause и @don_crissti:

     #!/bin/bash # adapted from http://unix.stackexchange.com/a/157594/110635 # and http://unix.stackexchange.com/a/220619/110635 W=1024 H=768 SIZE_TEST="%[fx:(h>$H && w>$W)]"'\n' for f in $*; do if [ $(identify -format "$SIZE_TEST" "$f") = 1 ]; then echo "Resize: $f" mogrify -resize ''"$W"x"$H"'' "$f" else echo "Do not resize: $f" fi done 

    (Мне это нужно, потому что мой любимый пакетный процессор Phatch не работает с Ubuntu 16.04.)

    Linux и Unix - лучшая ОС в мире.