Filtrando imagens de acordo com o nome do arquivo, por quê?

3

Ao filtrar as imagens usando o código abaixo, também preciso filtrar arquivos.

Por exemplo, IMG_0079.JPG.JPG , ao executar o código abaixo, é permitido que arquivos com .JPG adicional sejam filtrados, e não consigo descobrir por quê?

  • Verificando se a entrada está correta

    if [ $# != 2 ]; then
       echo "Usage: phar image_path archive_path" && exit;
    fi
    
  • Isso criará um diretório de destino se ele não existir

    mkdir -p $2
    
  • Declaração que localiza e copia e adiciona os sufixos necessários aos arquivos

    find $1 -iname IMG_[0-9][0-9][0-9][0-9].JPG -exec cp -b --suffix=.JPG 
    {} $2 \; 
    echo complete!
    
  • Verifique e remova a declaração duplicada. Ele irá comparar o md5 de cada arquivo.

        shopt -s nullglob              
        for file in "$2"/* 
        do
          md5sum=$(md5sum < "$file")        
          echo "-- Found: $file ($md5sum)"
          for duplicate in "$2"/*     #loop to find/remove duplicates
          do
            [ "$file" = "$duplicate" ] && continue      
            #comparison of 2 files
            [ "$md5sum" = "$(md5sum < "$duplicate")" ] && rm -v             
            "$duplicate"     
            #removal of duplicates
          done
        done
    
por Joseph 12.07.2014 / 00:02

2 respostas

2

Se eu estiver lendo isso corretamente, seu problema está aqui:

find $1 -iname IMG_[0-9][0-9][0-9][0-9].JPG

Isso nunca encontra os arquivos .JPG.JPG em primeiro lugar. Olhe:

mkdir JPG
for n in 9 8 7 6 5 4 3 2 1
    do touch ./JPG/IMG_000${n}.JPG
done
find ./JPG -iname IMG_[0-9][0-9][0-9][0-9].JPG

###OUTPUT###

./JPG/IMG_0001.JPG
./JPG/IMG_0002.JPG
./JPG/IMG_0003.JPG
./JPG/IMG_0004.JPG
./JPG/IMG_0005.JPG
./JPG/IMG_0006.JPG
./JPG/IMG_0007.JPG
./JPG/IMG_0008.JPG
./JPG/IMG_0009.JPG

Então agora eu vou ...

for f in ./JPG/* ; do touch ${f}.JPG ; done && ls ./JPG

IMG_0001.JPG      IMG_0003.JPG.JPG  IMG_0006.JPG      IMG_0008.JPG.JPG
IMG_0001.JPG.JPG  IMG_0004.JPG      IMG_0006.JPG.JPG  IMG_0009.JPG
IMG_0002.JPG      IMG_0004.JPG.JPG  IMG_0007.JPG      IMG_0009.JPG.JPG
IMG_0002.JPG.JPG  IMG_0005.JPG      IMG_0007.JPG.JPG
IMG_0003.JPG      IMG_0005.JPG.JPG  IMG_0008.JPG

Vamos ver o que o find nos mostra agora:

find ./JPG -iname IMG_[0-9][0-9][0-9][0-9].JPG

###OUTPUT###

./JPG/IMG_0001.JPG
./JPG/IMG_0002.JPG
./JPG/IMG_0003.JPG
./JPG/IMG_0004.JPG
./JPG/IMG_0005.JPG
./JPG/IMG_0006.JPG
./JPG/IMG_0007.JPG
./JPG/IMG_0008.JPG
./JPG/IMG_0009.JPG

Então, você vê, porque meus .JPG.JPG nomes de arquivos não terminam com a string [0-9]{4}.JPG find nunca os mostra em primeiro lugar. Adicionar um \* ao final dessa sequência de pesquisa -iname pode funcionar melhor para você.

Ainda assim, como a outra resposta menciona, outro problema é o seu shell globs. Por exemplo:

sh -cx 'cd ./JPG ; find . -iname IMG_[0-9][0-9][0-9][0-9].JPG'                                                                      
+ cd ./JPG
+ find . -iname IMG_0001.JPG IMG_0002.JPG IMG_0003.JPG IMG_0004.JPG IMG_0005.JPG IMG_0006.JPG IMG_0007.JPG IMG_0008.JPG IMG_0009.JPG
find: paths must precede expression: IMG_0002.JPG
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

Você vê? Se o shell puder, ele será [glob] nos colchetes não citados que você obteve antes mesmo de passar a string de comando para find . Provavelmente deve parecer mais com isso:

find "$1" -iname 'IMG_[0-9][0-9][0-9][0-9].JPG*'

E em relação ao último bit, talvez você não precise recursivamente fazer um loop muito. Eu acho - contanto que você esteja apenas procurando remover o antigo cp --suffix=.JPG -b ackups - isso pode funcionar como um substituto funcional para tudo, desde shopt... on:

(   dir=$2
    set -- "${dir}"/*[0-9].???
    while [ -e "$1" ]
    do  cmp "$1" "${1}.JPG" &&
        rm -v "${1}.JPG" 2>&1
    shift ; done
) 2>/dev/null

Embora, reconhecidamente, isso possa ser otimizado muito com um loop recursivo como:

(   dir=$2
    set -- "${dir}"/*[0-9].???
    while [ -e "$1" ]
    do  until [ -e "${1}.JPG" ] 
        do shift || break; done
        cmp "$1" "${1}.JPG" &&
        rm -v "${1}.JPG" 2>&1
    ${1+shift} ; done
) 2>/dev/null 

Eu digo mais ou menos porque os circuitos while e until operam no mesmo conjunto de parâmetros e nunca testam o mesmo arquivo duas vezes, então eles não exatamente recurse em> mesmo se eles estiverem aninhados. De qualquer forma, a otimização está em não exec em qualquer outro processo until necessário e contando apenas com builtins de shell, tanto quanto possível.

    
por 12.07.2014 / 02:29
2

O loop for que você mencionou está gerando um erro para mim. Mas funciona bem quando uso caractere de escape para colchetes. Então meu loop for seria assim:

find $1 -iname IMG_\[0-9\]\[0-9\]\[0-9\]\[0-9\].JPG -exec cp -b --suffix=.JPG  {} $2 \;
    
por 12.07.2014 / 00:25