如何让xargs执行的shell脚本接收用户输入?
原因说明
管道结构下,find命令的所有输出都会通过标准输入传递给xargs,xargs会将标准输入的内容全部读取为待处理的文件路径参数,这就导致xargs后续拉起的sh进程继承的标准输入已经被读完,处于EOF状态。当脚本执行read语句时,检测到标准输入为EOF会直接返回,不会等待用户输入。
你给出的测试用例xargs <<< "a.sh" sh同理:here string的内容全部被xargs读取为参数后,后续sh进程的标准输入为空,因此read直接跳过。
解决方法
方法1:使用GNU xargs的
-o(--open-tty)参数
该参数会将xargs拉起的命令的标准输入重定向到当前终端/dev/tty,不需要修改原有脚本,是最简单的方案,适配绝大多数Linux发行版环境。
修改后的命令为:find . -name "<pattern>" -print0 | xargs -0 -o sh你的测试用例对应修改为
xargs -o <<< "a.sh" sh即可正常等待用户输入。方法2:直接使用find的
-exec参数替代xargs
该场景下不需要通过xargs传递参数时,可直接用find自带的exec逻辑拉起脚本,此时脚本的标准输入默认继承当前终端,不会被占用:# 逐文件执行 find . -name "<pattern>" -exec sh {} \; # 批量传递执行,执行效率更高 find . -name "<pattern>" -exec sh {} +方法3:手动重定向脚本输入到终端(兼容性最好)
如果你使用的是BSD系xargs(如macOS默认xargs)不支持-o参数,可以手动给执行的脚本重定向标准输入到/dev/tty,全平台兼容:find . -name "<pattern>" -print0 | xargs -0 sh -c 'for script in "$@"; do sh "$script" < /dev/tty; done' _
内容的提问来源于stack exchange,提问作者gpanda
相关产品推荐
相关产品推荐

