Batch exclusão de arquivos menores do grupo de arquivos via linha de comando unix

3

Eu tenho um grande número (mais de 400) de diretórios cheios de fotos. O que eu quero fazer é manter os tamanhos maiores dessas fotos. Cada diretório tem 31 a 66 arquivos.

Cada diretório tem miniaturas e versões maiores, além de um arquivo chamado example.jpg

Eu enviei o arquivo example.jpg facilmente com:

rm */example.jpg

Inicialmente, achei que seria fácil excluir as miniaturas, mas o problema é que elas não são nomeadas de forma consistente. O padrão típico foi photo1.jpg e photo1s.jpg . Eu fiz rm */photo*s.jpg mas acabou alguns dos arquivos chamados photoXs.jpg eram realmente maiores e não menores. Argh.

Então, o que eu quero fazer é digitalizar cada diretório para o tamanho do arquivo e excluir (ou mover) as miniaturas. Inicialmente, pensei em usar apenas ls -R de cada arquivo e extrair o tamanho de cada arquivo e salvá-los em um limite. O problema? Em um diretório o grande será 1.1 MB e o polegar é 200k. Em outro, o grande é 200k e o pequeno 30k.

Ainda pior, os arquivos são na verdade denominados photo1.jpg - então colocá-los todos na mesma pasta, ordenar por tamanho e excluir em grupos não funcionaria sem renomear e, se possível, prefiro mantenha-os em suas pastas.

Eu estava quase decidido a fazer tudo isso manualmente, mas depois pensei em perguntar aqui.

Como você faria essa tarefa?

    
por artlung 29.04.2010 / 16:02

4 respostas

1

Esse script faz a suposição de que há uma lacuna significativa nos tamanhos entre os grupos de arquivos menores e maiores. Em particular, o menor dos arquivos grandes é pelo menos duas vezes maior que o maior dos arquivos pequenos.

Chame o script "imagedirstats" e execute-o em um loop como este:

find /path/to/main/branch -type d | while read subdir; do (cd "$subdir" && ~/bin/imagedirstats ); done

para encontrar e excluir arquivos em diretórios individuais na árvore de diretórios.

Aqui está o script:

#!/bin/bash
# from http://superuser.com/questions/135951/batch-deletion-of-smaller-files-from-group-of-files-via-unix-command-line
# by Dennis Williamson - 2010-04-29

prevn=1     # prevent division by zero
factor=4    # how close to the largest of the small files to set the threshold, 4 == one fourth of the way above
min=1000    # ignore files below this size

while read n
do
    (( ratio = n / prevn ))
    if (( ratio > 1 && n > min ))
    then
        break
    fi
    if (( n > 0 ))
    then
        prevn=$n
    fi
done < <(find . -maxdepth 1 -name "*.jpg" -printf "%s\n" | sort -n)
# for OS X, comment out the preceding line and uncomment this one:
# done < <(find . -maxdepth 1 -name "*.jpg" | stat -f "%z" | sort -n)

# the following line would be the GNU equivalent using stat(1) instead of printf
# it's included here for reference:
# done < <(find . -maxdepth 1 -name "*.jpg" | stat -c "%s" | sort -n)

(( size = (n - prevn) / factor + prevn ))

echo "Smallest of the large: $n"
echo "Largest of the small: $prevn"
echo "Ratio: $ratio"
echo "Threshold: $size"

if (( ratio < 2 ))
then
    read -p "Warning: ratio too small. Delete anyway? Only 'Yes' will proceed" reply
    if [[ $reply != "Yes" ]]
    then
        echo "Cancelled" >&2
        exit 1
    fi
fi

# uncomment the delete on the following line to actually do the deletion

find . -maxdepth 1 -name "*.jpg" -size -${size}c # -delete

Editar: Movido o aviso para que informações úteis sejam exibidas primeiro. Corrigido um fi ausente.

Editar 2: Tornou os dois comandos find consistentes. Adicionada uma variação comentada do OS X. Adicionadas informações sobre a execução do script.

    
por 29.04.2010 / 17:04
4

Se houver algum cutoff específico que você possa encontrar, por exemplo, todas as imagens grandes são maiores que 200 KB, você pode fazer isso:

find */*.jpg -size -200k -delete

Você pode querer fazer uma cópia de backup primeiro.

    
por 29.04.2010 / 16:28
3

Se os tamanhos dos arquivos não forem consistentes, as dimensões da imagem?

Você pode usar o identify , uma ferramenta que acompanha o ImageMagick, para capturar as dimensões da imagem. Por meio de alguns scripts simples, você pode trabalhar com as imagens dependendo do tamanho delas.

Para capturar a largura e a altura de uma imagem com identify :

identify -format '%wx%h' filename

você terá uma saída assim:

[john@awesome:~]$ identify -format '%wx%h' W4.JPG
1680x1050

Você pode usar o utilitário cut para capturar os números no seu script:

[john@awesome:~]$ identify -format '%wx%h' W4.JPG | cut -d'x' -f1
1680
[john@awesome:~]$ identify -format '%wx%h' W4.JPG | cut -d'x' -f2
1050
    
por 29.04.2010 / 16:20
0

Se você quiser fazer isso com base no nome do arquivo, tente o seguinte:

find -name '*.jpg' | sed -ne 's:^\(.*\)\.jpg:s.jpg$:p' | xargs rm

Ele encontrará todos os arquivos .jpg, colocará um "s" no final do nome do arquivo (logo antes do ".") e o excluirá.

    
por 29.04.2010 / 16:53