Condição de script Bash sempre passando mesmo quando o grep não devolver nada

3

Estou tendo problemas ao tentar retornar o arquivo de imagem que se ajusta aos parâmetros. $ 1 é o parâmetro de pesquisa, neste incidente é "real", que é uma tag em uma das imagens (não duas) na pasta dada. O que acontece quando eu chamo de "./test.sh real" é imprimir ambas as imagens, ao invés de apenas uma. Eu imagino que tem que lidar comigo configurando o retorno da função como uma variável e / ou minha condição, mas não tenho certeza.

#!/bin/bash
for f in specim/*.jpg
do
    image=$(exiftool -EXIF:XPKeywords $f | grep "$1")
    if [[ !  -z  "$image// }"  ]]; then
    echo $f
fi

o que é retornado:

../../test.sh real
specim/image2.jpg
specim/image.jpg

Este script bash imprime o que eu quero, apenas uma imagem em vez de ambas (como as coisas exiftool que eu não quero, mas isso foi apenas um teste):

#!/bin/bash
for f in *.jpg
do
    exiftool -EXIF:XPKeywords $f | grep $1
done

resultado:

./test2.sh real
XP Keywords                     : name;real

qualquer ajuda seria apreciada e é provavelmente super simples ... Obrigado

    
por soulkingbrook 23.09.2015 / 23:42

4 respostas

5

Provavelmente, como você suspeitou, apenas uma pequena alteração a ser corrigida, tente:

if [[ !  -z  "$image"  ]]; then

Explicação

Digamos que quando houver uma correspondência por exiftool e grep, sua variável $image contenha isso:

abcabcabc

Mas quando não há saída, $image contém: (nada)

Na sua condição de teste, você tinha:

if [[ !  -z  "$image// }"  ]]; then

Então, no primeiro caso, o bash vê isso:

if [[ !  -z  "abcabcabc// }"  ]]; then

Mas no segundo caso, bash vê isso:

if [[ !  -z  "// }"  ]]; then

O teste está dizendo que if "// }" is NOT zero-value, then... , no entanto, "// }" será sempre o valor zero, é algo, é uma string que consiste em duas barras, um espaço e uma chave. Portanto, como há algo lá, algo que não é de valor zero, é por isso que a parte then é acionada mesmo quando você não tem correspondências em $image . Então, removendo este // } , deve funcionar.

    
por 24.09.2015 / 00:02
3

Outra opção pode ser:

if [[ -n "$image" ]]; then

para verificar se apenas a variável $image contém algo, em vez de ! -z ...

    
por 24.09.2015 / 00:05
3

Você está executando exiftool e grep (+ um teste e eco) para cada .jpg nesse diretório ... não é muito eficiente ...
exiftool pode fazer tudo isso sozinho a opção -if EXPR , por exemplo

exiftool -q -s3 -if '$tag=~/pattern/' -filename ./*.jpg

(aqui combinado com -q - quiet e -s[NUM] - formato de saída curto: apenas valores de impressão, consulte o manual para obter mais detalhes)
Então, no seu caso particular, todo o script pode ser substituído por:

exiftool -q -s3 -if \$Exif:XPKeywords=~/"$1"/ -filename specim/*.jpg

por exemplo. executando o script test.sh com quatro arquivos de teste que possuem os seguintes valores XPKeywords :

exiftool -Exif:XPKeywords specim/*.jpg
======== specim/1.jpg
XP Keywords                     : xname;real
======== specim/2.jpg
XP Keywords                     : yname;different
======== specim/3.jpg
XP Keywords                     : wname;true
======== specim/4.jpg
XP Keywords                     : wname;unreal
    4 image files read

executando test.sh real retornos:

1.jpg
4.jpg

e test.sh unreal retornam:

4.jpg
    
por 24.09.2015 / 01:45
1
O status de saída do

grep é se ele corresponde ou não a alguma coisa, então por que capturar a saída do grep e então testá-lo, como uma string, para o vazio? Você poderia fazer

if exiftool -EXIF:XPKeywords $f | grep -q "$1" ; then
    echo $f
fi

se você quiser.

    
por 24.09.2015 / 04:33