我试图为提交几个不同的git项目创建一个别名。我试过像
这样的东西cat projectPaths | \
xargs -I project git --git-dir=project/.git --work-tree=project commit -a
其中projectPaths是一个文件,包含我要提交的所有项目的路径。这似乎在很大程度上起作用,按顺序为每个项目启动vi,以便我可以为它编写一个提交消息。但是,我确实得到了一个消息:
“Vim:警告:输入不是来自终端”
然后我的终端很奇怪:它没有显示我输入的文本,似乎没有输出任何换行符。当我进入“重置”时,事情几乎恢复正常,但显然我做错了。
有没有办法在不弄乱shell的情况下获得相同的行为?
谢谢!
答案 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的一个问题: