La guía paso a paso o código que hallarás en este post es la resolución más rápida y efectiva que encontramos a tus dudas o problema.
Solución:
pienso mogrify
reescribe sistemáticamente el archivo, por lo que su única esperanza es filtrar la lista primero, como sugiere jippie. Así es como puede hacerlo (no probado): imprima una lista de archivos de imagen con una indicación de tamaño, conserve solo los nombres cuyo tamaño asociado esté dentro del rango y procese esa lista.
identify -format '%w %h %in' ./*.png |
awk '$1 > 400 || $2 > 400 sub(/^[^ ]* [^ ]* /, ""); print' |
tr 'n' ' ' |
xargs -0 mogrify -resize '400x400'
Explicación del guión:
- Para cada archivo, imprima una línea con el ancho, un espacio, la altura, un espacio y el nombre del archivo. Dependiendo de su versión de
identify
lan
agregar una nueva línea final puede ser necesario (ImageMagick 6.6.0) o superfluo pero inofensivo (GraphicsMagick 1.1.11). - (
awk
) En cada línea, si el ancho ($1
) y altura ($2
) coincida con las condiciones requeridas, entonces:- Elimina todo el texto hasta el segundo carácter de espacio. Esto quita el ancho y la altura.
- Imprime lo que queda de la línea, que es el nombre del archivo.
- Reemplazar líneas nuevas por null caracteres.
- Llamar
xargs -0
para ejecutar elmogrify
comando en los nombres de archivo. (No podemos usar simplexargs
porque no puede manejar entradas que contengan espacios en blanco o'"
.)
Los nombres de los archivos pueden contener cualquier carácter excepto líneas nuevas.
Enfrenté el mismo problema que describiste. Aquí está mi solución:
#!/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
Lo probé en varias imágenes JPEG en una máquina CentOS 6.5 virtualizada. El script solo redimensionaba y comprimía las imágenes cuyo ancho o alto superaba los 640 píxeles. Esto hizo que funcionara para imágenes con dimensiones como 800 x 600 (horizontal, redimensionándolo a 640 x 480) y dimensiones como 600 x 800 (retrato, redimensionándolo a 480 x 640).
PD: Una nota sobre el 400x400
parámetro: mogrify
procesará el archivo incluso si sus dimensiones son iguales o inferiores a 400×400, pero cambiar el tamaño sólo si sus dimensiones son superiores a 400×400. Por eso se cambia el tiempo de modificación y el tamaño de los archivos (en mi caso, mogrify
hizo estos archivos incluso más grande de lo que eran).
También podrías usar el fx
operador para filtrar imágenes en función de la altura/anchura, por ejemplo
identify -format '%[fx:(h>400 && w>400)]n' image.png
dará salida 1
si la imagen es más grande que 400x400
y 0
si es igual o menor que 400x400
…
Asumiendo nombres de archivos sanos (sin líneas nuevas/espacios/pestañas, etc.) que podría usar identify
para imprimir nombres de imágenes precedidos por 1:
o 0:
procesa la salida eliminando las líneas que comienzan con 0:
y eliminando el líder 1:
en el resto de líneas para que solo queden los nombres de archivo, uno por línea, luego canalice esa lista a mogrify ... @-
(la @
la sintaxis fue añadida en imagemagick v6.5.2
):
identify -format '%[fx:(h>400 && w>400)]:%in' ./*.png |
sed '/^1:/!d;//s///' | mogrify -resize '400x400' -- @-
De lo contrario, con find
podría imprimir solo los archivos con un tamaño> 400×400 y luego canalizar el resultado a xargs
+ mogrify
(es menos eficiente ya que ejecuta un shell para cada archivo, pero debería funcionar con todo tipo de nombres de archivo):
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'
si eres un zsh
usuario ver también esta respuesta.