4

I have a very simple shell script that should remove floating docker images, the command for this is: docker rmi $(docker images -f "dangling=true" -q)

Now I'm running into an issue which I think is caused by the $. I might be wrong though.

My script is this:

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

When I run this though, it prints out to the screen:

"docker rmi" requires at least 1 argument.

See 'docker rmi --help'.

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

Remove one or more images

I'm making an assumption that's because of the $(docker imag...) part and of course $ is a special character.

How do I go about escaping or at least getting my script to behave in the way I would like?

1 Answer 1

4

The $(...) operator, called command substitution, is the one that expands to the standard output of a command stripped of its trailing newline characters.

When unquoted and in list contexts, it's also subject to split+glob (split only in zsh).

For instance, if cmd outputs *:x\n\n and $IFS contains :, $(cmd) would expand to *:x and in list context, that would split into * and x and that * would be expanded to the list of files in the current directory.

So typically:

cmd1 $(cmd2)

with the default value of $IFS (space, tab and newline) is meant to pass to cmd1 the list of files that match the list of (space/tab/newline delimited) patterns output by cmd2.

Here, given the error message output by your cmd1, it looks like your cmd2 outputs nothing or only space, tab, newlines characters which results in no arguments passed to cmd1.

So, you may need to take care of that special case first like:

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

Or with GNU or FreeBSD xargs do:

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

That would also avoid the words output by docker images from being treated as file patterns. xargs expects a blank+newline delimited list of words which it passes as argument to the command and also understands some forms of quotings. It you wanted to pass one argument for each line of input, you'd use (with GNU xargs):

docker images -f dangling=true -q |
  xargs -rd '\n' docker rmi
1
  • phew, i thought my question might be a duplicate, but i couldn't find anything referenced. Thanks for the detailed answer.
    – Jarede
    Jan 4, 2018 at 12:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .