在命令中转义一美元?

在命令中转义一美元?

我有一个非常简单的 shell 脚本,应该删除浮动的 docker 图像,命令是:docker rmi $(docker images -f "dangling=true" -q)

现在我遇到了一个问题,我认为是由$.但我可能是错的。

我的脚本是这样的:

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

当我运行它时,它会打印到屏幕上:

“docker rmi”需要至少 1 个参数。

请参阅“docker rmi --help”。

用法:docker rmi [选项] IMAGE [IMAGE...]

删除一张或多张图像

我做出的假设是因为这个$(docker imag...)角色,当然$是一个特殊的角色。

我该如何逃脱或者至少让我的脚本按照我想要的方式运行?

答案1

运营$(...)商称为命令替换,是扩展为删除其尾随换行符的命令的标准输出的输出。

当不加引号并且在列表上下文中时,它也受到 split+glob (分裂只有在zsh)。

例如,如果cmd输出*:x\n\n$IFScontains :,$(cmd)将扩展为*:x和 在列表上下文中,它将拆分为*x,并将*扩展为当前目录中的文件列表。

所以通常:

cmd1 $(cmd2)

默认值为$IFS(空格、制表符和换行符)意味着传递到与 .cmd1输出的(空格/制表符/换行符分隔)模式列表匹配的文件列表cmd2

在这里,给出您的错误消息输出cmd1,看起来像你的cmd2不输出任何内容或仅输出空格、制表符、换行符,这会导致没有参数传递给cmd1.

因此,您可能需要首先处理这种特殊情况,例如:

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

或者使用 GNU 或 FreeBSDxargs执行以下操作:

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

这也将避免输出的单词被docker images视为文件模式。xargs需要一个空白+换行符分隔的单词列表,它作为参数传递给命令,并且还理解某些形式的引用。如果您想为每一行输入传递一个参数,您可以使用(使用 GNU xargs):

docker images -f dangling=true -q |
  xargs -rd '\n' docker rmi

相关内容