我设置了一个管道,返回我想要安装的包的名称,使用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 _
请注意,一次传递所有包可能apt
比apt
每个包调用一个包更有意义。
sudo xargs -d '\n' -ra <(cmd) apt install
(-d
是另一个 GNU 扩展)
在任何情况下,就像在管道版本中一样,无论是否成功,pipefail
都将运行,因为和是同时启动并并发运行的。sudo
cmd
sudo
cmd