带有命令的xargs,打开编辑器将shell留在奇怪的状态

ini*_*nch 14 unix vi bash scripting

我尝试为提交几个不同的git项目创建一个别名.我试过类似的东西

cat projectPaths | \
xargs -I project git --git-dir=project/.git --work-tree=project commit -a
Run Code Online (Sandbox Code Playgroud)

其中projectPaths是一个文件,包含我要提交的所有项目的路径.这似乎在很大程度上起作用,按顺序为每个项目启动vi,以便我可以为它编写一个提交消息.但是,我得到一个消息:

"Vim:警告:输入不是来自终端"

然后我的终端很奇怪:它没有显示我输入的文本,似乎没有输出任何换行符.当我进入"重置"时,事情几乎恢复正常,但显然我做错了什么.

有没有办法在不弄乱shell的情况下获得相同的行为?

谢谢!

hta*_*ess 14

使用更简单的例子

ls *.h | xargs vim
Run Code Online (Sandbox Code Playgroud)

以下是解决问题的几种方法:

xargs -a <( ls *.h ) vim
Run Code Online (Sandbox Code Playgroud)

要么

vim $( ls *.h | xargs )
Run Code Online (Sandbox Code Playgroud)

要么

ls *.h | xargs -o vim
Run Code Online (Sandbox Code Playgroud)

一个示例使用xargs -a(--arg-file)标志,该​​标志告诉xargs从文件而不是标准输入获取其输入.在这种情况下,我们提供的文件是bash 进程替换而不是常规文件.

进程替换将包含在其中的命令的输出<( )放在filedescriptor中,然后替换filedescriptor,在这种情况下,替换命令将是类似的xargs -a /dev/fd/63 vim.

所述第二命令使用命令替换,命令将在子Shell中执行,和它们的标准输出数据被取代.

第三个命令使用xargs的--open-tty(-o)标志,该手册页介绍正是如此:

在执行命令之前,在子进程中将stdin重新打开为/ dev/tty.如果您希望xargs运行交互式应用程序,这将非常有用.

如果您使用旧方法并希望让终端再次运行,则可以使用该reset命令.


Gor*_*son 12

问题是,因为你在管道中运行xargs(因此是git,因此是vim),所以它的stdin取自输出cat projectPaths而不是终端; 这让vim感到困惑.幸运的是,解决方案很简单:将-o标志添加到xargs,它将使用/ dev/tty的输入而不是自己的stdin启动git(以及vim).