escapando de um dólar em um comando?

4

Eu tenho um script de shell muito simples que deve remover imagens flutuantes do docker, o comando para isso é: docker rmi $(docker images -f "dangling=true" -q)

Agora estou encontrando um problema que acho que é causado pelo $ . Eu posso estar errado.

Meu script é este:

#!/bin/bash
cd /Users/jared/Projects
for d in ./*/ ;
do (cd "$d" && docker rmi $(docker images -f "dangling=true" -q); true); done

Quando eu executo isso, ele é exibido na tela:

"docker rmi" requires at least 1 argument.

See 'docker rmi --help'.

Usage: docker rmi [OPTIONS] IMAGE [IMAGE...]

Remove one or more images

Estou fazendo uma suposição que é por causa da parte $(docker imag...) e, claro, $ é um caractere especial.

Como faço para escapar ou pelo menos fazer meu script se comportar da maneira que gostaria?

    
por Jarede 04.01.2018 / 12:27

1 resposta

4

O operador $(...) , chamado substituição do comando , é aquele que se expande para a saída padrão de um comando livre de seus caracteres de nova linha.

Quando não está em lista e em contextos de lista, também está sujeito a split + glob ( split apenas em zsh ).

Por exemplo, se cmd outputs *:x\n\n e $IFS contiver : , $(cmd) expandiria para *:x e, no contexto da lista, seria dividido em * e x e * seria expandido para a lista de arquivos no diretório atual.

Então, normalmente:

cmd1 $(cmd2)

com o valor padrão de $IFS (espaço, tabulação e nova linha) destina-se a passar para cmd1 a lista de arquivos que correspondem à lista de padrões (espaço / guia / nova linha delimitada) gerados por cmd2 .

Aqui, dada a mensagem de erro emitida pelo cmd1 , parece que o seu cmd2 não produz nada ou apenas espaço, tabulação, caracteres de nova linha que resultam em nenhum argumento foi passado para cmd1 .

Então, você pode precisar cuidar desse caso especial primeiro, como:

set -- $(docker images -f dangling=true -q)
[ "$#" -eq 0 ] || docker rmi "$@"

Ou com o GNU ou FreeBSD xargs do:

docker images -f dangling=true -q |
  xargs -r docker rmi

Isso também evitaria que as palavras produzidas por docker images fossem tratadas como padrões de arquivo. xargs espera uma lista delimitada em branco + nova linha de palavras que ela passa como argumento para o comando e também entende algumas formas de citações. Você queria passar um argumento para cada linha de entrada, você usaria (com GNU xargs ):

docker images -f dangling=true -q |
  xargs -rd '\n' docker rmi
    
por 04.01.2018 / 12:44