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

时间:2010-10-04 03:09:36

标签: bash unix scripting vi

我试图为提交几个不同的git项目创建一个别名。我试过像

这样的东西
cat projectPaths | \
xargs -I project git --git-dir=project/.git --work-tree=project commit -a

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

  

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

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

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

谢谢!

5 个答案:

答案 0 :(得分:14)

使用

的简单例子
ls *.h | xargs vim

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

xargs -a <( ls *.h ) vim

vim $( ls *.h | xargs )

ls *.h | xargs -o vim

第一个示例使用xargs -a--arg-file)标志,该​​标志告诉xargs从文件而不是标准输入中获取输入。在这种情况下,我们提供的文件是bash process substitution而不是常规文件。

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

第二个命令使用command substitution,命令在子shell中执行,并且他们的stdout数据被替换。

第三个命令使用xargs --open-tty-o)标志,该​​手册页由此描述:

  

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

如果您确实以旧方式使用它,并希望让终端再次运行,则可以使用reset命令。

答案 1 :(得分:12)

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

答案 2 :(得分:2)

GNU xargs的手册页显示了针对emacs的类似命令:

xargs sh -c 'emacs "$@" < /dev/tty' emacs

(在此命令中,第二个“emacs”是Wisbucky在对此答案的评论中引用的“虚拟字符串”)

并说:

   Launches  the  minimum  number of copies of Emacs needed, one after the
   other, to edit the files listed on xargs' standard input.  This example
   achieves the same effect as BSD's -o option, but in a more flexible and
   portable way.

要尝试的另一件事是使用-a代替cat

xargs -a projectPaths -I project git --git-dir=project/.git --work-tree=project commit -a

或两者的某种组合。

答案 3 :(得分:1)

如果你安装了GNU Parallel http://www.gnu.org/software/parallel/,你应该可以这样做:

cat projectPaths |
parallel -uj1 git --git-dir={}/.git --work-tree={} commit -a

一般来说,这也有效:

cat filelist | parallel -Xuj1 $EDITOR

如果您想一次编辑多个文件(并且已将$ EDITOR设置为您喜欢的编辑器)。

-o的{​​{1}}(如其他地方所述)仅适用于某些版本的xargs(特别是对GNU xargs不起作用)。

观看介绍视频,详细了解GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ

答案 4 :(得分:0)

有趣!我在Mac上也看到了完全相同的行为,做了一些简单的事情:

ls * .h | xargs vim

显然,这是vim的一个问题:

http://talideon.com/weblog/2007/03/xargs-vim.cfm