find: o nome do arquivo atual é avaliado como vazio no comando aninhado

0

Estou tentando renomear um monte de imagens em um diretório de acordo com suas dimensões. Para esse fim, estou construindo meu comando passo a passo, usando o comando identify do Imagemagik. No momento, estou usando echo e pretendo alterar isso para mv once echo corretamente.

find * -type f -exec echo "$(identify -format '%w-%h' {})" \;

Isso gera um monte de linhas vazias. No entanto, quando eu apenas corro sem o eco diretamente,

find * -type f -exec identify -format '%w-%h' {} \;

Produz as dimensões conforme esperado. Por que o comando interno não está sendo executado corretamente?

    
por Jeff 25.09.2017 / 19:33

2 respostas

1

Uso:

find . -type f -exec sh -c 'echo "$(identify -format %w-%h "$1")"' sh {} \;

Explicação

O problema é com o modo como o bash expande as variáveis

find * -type f -exec echo "$(identify -format '%w-%h' {})" \;

O primeiro bash expande o que está no lado $(...) :

find * -type f -exec echo 'identify: unable to open image '{}': No such file or directory...' \;

Nesse ponto, o find usará a mesma instrução exec para todos os comandos com um argumento inútil. O que você quer fazer é suprimir a expansão bash para dentro do executável localiza. Você pode parar de expandir as coisas colocando-as entre aspas simples

find * -type f -exec echo '$(identify -format %w-%h {})' \;

Mas aqui perdemos a expansão completamente, podemos injetar de volta executando a expressão com sh -c

find * -type f -exec sh -c 'echo "$(identify -format %w-%h {})"' \;

Ter {} dentro do script de shell também pode levar a alguns erros inesperados ao lidar com espaço em branco ou aspas ou qualquer caractere especial ao shell nos nomes de arquivo. Para contornar isso, você deve mover o {} como argumento para:

find * -type f -exec sh -c 'echo "$(identify -format %w-%h "$1")"' sh {} \;

Veja esta pergunta / resposta para uma explicação mais detalhada sobre isso.

Por fim, você pode substituir o * por . para deixar find localizar os arquivos no diretório atual por si só (e incluir os ocultos e não falhar para nomes de arquivos que começam com - ).

Além disso, você pode adicionar o -x flag a sh para que ele imprima o que foi executado para ajudar a depurar o comando - isso pode ser muito barulhento para muitos arquivos.

    
por 25.09.2017 / 19:44
2

Isso porque echo não sabe o que é {} dentro de si para expandi-lo, somente exec understand {} , nesse caso você deve usar no modo sh -c .

find . -type f -exec sh -c 'echo "$(identify -format '%w-%h' "$1")"' sh '{}' \;
    
por 25.09.2017 / 19:41

Tags