Gerar e mover miniaturas recursivamente

7

Eu quero um script bash que faça o seguinte:

  • Encontre imagens (jpg, jpeg, JPG, JPEG) de forma recursiva do diretório atual para baixo
  • Gerar uma miniatura com o convert do imagemagick
  • Mover a miniatura para outro diretório

Meu script atual é assim:

for f in 'find . -type f -iname "*.jpg"'
  do
  convert ./"$f" -resize 800x800\> ./"${f%.jpg}_thumb.jpg"
  mv ./"${f%.jpg}_thumb.jpg" /home/user/thumbs/
done

Não converte arquivos (ou pastas com todo o conteúdo) com espaços / caracteres especiais. Eu tentei com print0 , mas isso não ajudou.

    
por LucaTony 26.12.2016 / 21:49

3 respostas

5

Você pode usar opções mais avançadas, como -set combinadas com por cento escapa (ou seja, %t para extrair o nome do arquivo sem diretório ou extensão) para fazer o redimensionamento , renomear e mover cada arquivo com uma única invocação convert :

find . -type f -iname \*.jpg -exec convert {} -resize 800x800\> \
-set filename:name '%t' '/home/user/thumbs/%[filename:name]_thumb.jpg' \;
    
por 27.12.2016 / 00:30
5

Não itere a saída de find . O problema que você está enfrentando é uma conseqüência típica disso.

Seu exemplo é um pouco complicado devido à renomeação do arquivo. Uma maneira não muito eficiente, mas segura, é com a opção -exec de find e um sh adicional por cada arquivo, como este:

find . -type f -iname "*.jpg" -exec sh -c 'echo convert "$1" -resize 800x800\> /home/user/thumbs/"${1%.jpg}_thumb.jpg"' -- {} \;

Se você não se importou em usar o mesmo nome (com .jpg suffix em vez de _thumb.jpg ), esse formulário simples funcionaria e seria muito mais eficiente:

find . -type f -iname "*.jpg" -exec echo convert "{}" -resize 800x800\> /home/user/thumbs/"{}" \;

Eu adicionei echo declarações lá para verificar a saída antes de executar os comandos. Remova-os se a saída parecer boa.

    
por 26.12.2016 / 22:14
2

Na sua solução, os nomes dos arquivos foram divididos no $IFS padrão, que inclui espaços.

Tente o seguinte:

while IFS= read -rd '' f; do

    convert ./"$f" -resize 800x800\> ./"${f%.jpg}_thumb.jpg"
    mv ./"${f%.jpg}_thumb.jpg" /home/user/thumbs/

done < <(find . -type f -iname "*.jpg" -print0)

O find imprime os nomes dos arquivos separados por bytes nulos ( -d '' ) e usando read você define o delimitador de %code% para o mesmo.

    
por 26.12.2016 / 21:53