如何将 xargs 与需要用户输入的命令一起使用?

如何将 xargs 与需要用户输入的命令一起使用?

我设置了一个管道,返回我想要安装的包的名称,使用apt-get

... | xargs -I _ sudo apt install _

但是,apt-get在这种情况下无法从标准输入读取并退出:

你想继续吗? [是/否] 中止。

我知道-y无需用户确认即可安装软件包的标志,但我想实际看到确认。

有没有办法将包名称转发到,apt-get同时仍然允许它从标准输入读取?

放在apt-get整个命令的左侧不是一个选项,因为apt-get如果使用该选项中止管道中的较早命令,我不想执行该命令set -o pipefail

答案1

pipefail不会阻止管道右侧的运行,整个管道像往常一样同时运行。尝试例如

$ set -o pipefail
$ false | echo foo
foo

如果没有输入,它的使用xargs可能会也可能不会阻止在这里运行。apt如果没有-r-I它仍然会至少运行该命令一次。

但是您可以通过使用命令替换捕获输出然后apt根据结果运行或不运行来解决这个问题:

if packages=$(somecmd...) && [ "$packages" ] ; then
    set -f
    sudo apt install $packages
fi

包名称不应包含任何空格,因此使用$packages不带引号的应该可以工作(假设默认值为$IFS;它们可能也不能包含全局字符,因此set -f可能是不必要的)。

答案2

通过 GNU 实现xargs(通常在也有apt命令的系统上找到)和像 ksh93/zsh/bash 这样支持进程替换的 shell,您可以执行以下操作:

sudo xargs -I _ -ra <(cmd) apt install _

代替:

cmd | xargs -I _ sudo apt install _

请注意,一次传递所有包可能aptapt每个包调用一个包更有意义。

sudo xargs -d '\n' -ra <(cmd) apt install

-d是另一个 GNU 扩展)

在任何情况下,就像在管道版本中一样,无论是否成功,pipefail都将运行,因为和是同时启动并并发运行的。sudocmdsudocmd

相关内容