Script de shell para separar e mover imagens de paisagem e retrato

6

Eu tenho um diretório de jpg images. Existe um script de shell ( bash ou zsh seria aceitável) que moveria todas as imagens de paisagem para um diretório e todas as imagens de retrato para outro diretório?

    
por Raphael Rafatpanah 07.07.2016 / 05:06

3 respostas

7

Você pode usar imagemagick do identify com o operador fx especial para comparar a altura e a largura. %código%. Se for true, será gerado h>w , se falso, será emitido 1 :

for f in ./*.jpg
do
  r=$(identify -format '%[fx:(h>w)]' "$f")
  if [[ r -eq 1 ]] 
  then
      mv "$f" /path/to/portraits
  else
      mv "$f" /path/to/landscapes
  fi
done

Com 0 você pode usar o qualificador zsh string (para selecionar apenas os arquivos para os quais o código entre aspas retorna e ) e fazer algo como:

mv ./*.jpg(.e_'identify -format "%[fx:(h>w)]" $REPLY | grep 0 >/dev/null'_) /path/to/landscapes
mv ./*.jpg /path/to/portraits

para que o primeiro comando mova todas as imagens de paisagem para true e o segundo mova as imagens restantes para /path/to/landscapes .

As soluções acima tratarão imagens quadradas como paisagens e as moverão para o respectivo diretório. Você poderia introduzir uma segunda condição se quisesse movê-las para seu próprio diretório:

mv ./*.jpg(.e_'identify -format "%[fx:(h<w)]" $REPLY | grep 1 >/dev/null'_) /path/to/landscapes
mv ./*.jpg(.e_'identify -format "%[fx:(h>w)]" $REPLY | grep 1 >/dev/null'_) /path/to/portraits
mv ./*.jpg /path/to/squares

ou você pode usar uma condição diferente (por exemplo, verificar /path/to/portraits ratio) para separar as imagens quadradas do restante e deixá-las no diretório atual:

for f in ./*.jpg
do
  r=$(identify -format '%[fx:(h/w)]' "$f")
  if [[ r -gt 1 ]] 
  then
      mv "$f" /path/to/portraits
  elif  [[ r -lt 1 ]]
  then
      mv "$f" /path/to/landscapes
  fi
done
    
por 07.07.2016 / 12:54
3

Usando identify do ImageMagick:

#! /bin/sh                                            
identify -format '%w %h %i\n' -- "$@" 2>/dev/null | \
    while read W H FN; do
        if [ $W -gt $H ]; then
            echo mv -f -- "$FN" /path/to/landscape/
        else
            echo mv -f -- "$FN" /path/to/portraits/
        fi
    done

Isso não é particularmente eficiente porque executa mv para cada arquivo, mas você não pediu eficiência.

    
por 07.07.2016 / 12:55
3

Isso usa o utilitário fileinfo para obter a largura e a altura de uma imagem. Se a altura for maior que a largura, o arquivo será movido para o diretório portraits/ . Caso contrário, ele é movido para o diretório landscape/ .

for f in ./*jpg
do
    if fileinfo "$f" 2>&1 | awk '/w =/{w=$3+0; h=$6+0; if (h>w) exit; else exit 1}'
    then
        mv "$f" portraits/
    else
        mv "$f" landscape/
    fi
done

O nome do arquivo nesse loop é colocado nas aspas duplas onde for necessário, de modo que esse loop seja seguro para uso, mesmo para nomes de arquivos de imagem com espaços, novas linhas ou outros caracteres difíceis.

Em um sistema parecido com o debian, fileinfo pode ser instalado via:

apt-get install leptonica-progs

Outros utilitários similares podem ser usados contanto que o comando awk seja modificado apropriadamente.

    
por 07.07.2016 / 05:31