xargs 带有打开编辑器的命令使 shell 处于奇怪的状态

发布于 2024-09-26 14:11:55 字数 443 浏览 5 评论 0原文

我尝试为提交几个不同的 git 项目创建一个别名。我尝试了类似的方法

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

,其中projectPaths是一个文件,其中包含我想要提交的所有项目的路径。这似乎在大多数情况下都有效,为每个项目依次启动 vi,以便我可以为其编写提交消息。不过,我确实收到一条消息:

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

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

有没有什么方法可以在不弄乱我的外壳的情况下获得相同的行为?

谢谢!

I tried to make an alias for committing several different git projects. I tried something like

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

where projectPaths is a file containing the paths to all the projects I want to commit. This seems to work for the most part, firing up vi in sequence for each project so that I can write a commit msg for it. I do, however, get a msg:

"Vim: Warning: Input is not from a terminal"

and afterward my terminal is weird: it doesn't show the text I type and doesn't seem to output any newlines. When I enter "reset" things pretty much back to normal, but clearly I'm doing something wrong.

Is there some way to get the same behavior without messing up my shell?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

濫情▎り 2024-10-03 14:11:55

使用这里更简单的示例

ls *.h | xargs vim

有几种解决问题的方法:

xargs -a <( ls *.h ) vim

vim $( ls *.h | xargs )

ls *.h | xargs -o vim

first 示例使用 xargs -a (--arg-file) 标志告诉 xargs 从文件而不是标准输入中获取输入。在本例中,我们提供的文件是 bash 进程替换,而不是常规文件文件。

进程替换获取 <( ) 中包含的命令的输出,将其放入文件描述符中,然后替换该文件描述符,在这种情况下,替换的命令将类似于 xargs -a /dev /fd/63 vim.

第二个命令使用命令替换,命令为在子 shell 中执行,并且它们的标准输出数据被替换。

third 命令使用 xargs --open-tty (-o) 标志,手册页对此进行了如下描述:

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

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

Using the simpler example of

ls *.h | xargs vim

here are a few ways to fix the problem:

xargs -a <( ls *.h ) vim

or

vim $( ls *.h | xargs )

or

ls *.h | xargs -o vim

The first example uses the xargs -a (--arg-file) flag which tells xargs to take its input from a file rather than standard input. The file we give it in this case is a bash process substitution rather than a regular file.

Process substitution takes the output of the command contained in <( ) places it in a filedescriptor and then substitutes the filedescriptor, in this case the substituted command would be something like xargs -a /dev/fd/63 vim.

The second command uses command substitution, the commands are executed in a subshell, and their stdout data is substituted.

The third command uses the xargs --open-tty (-o) flag, which the man page describes thusly:

Reopen stdin as /dev/tty in the child process before executing the
command. This is useful if you want xargs to run an interactive
application.

If you do use it the old way and want to get your terminal to behave again you can use the reset command.

思慕 2024-10-03 14:11:55

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

The problem is that since you're running xargs (and hence git and hence vim) in a pipeline, its stdin is taken from the output of cat projectPaths rather than the terminal; this is confusing vim. Fortunately, the solution is simple: add the -o flag to xargs, and it'll start git (and hence vim) with input from /dev/tty, instead of its own stdin.

紫轩蝶泪 2024-10-03 14:11:55

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

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

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

并说: :

 启动所需的最小数量的 Emacs 副本,在
   其他,编辑 xargs 标准输入上列出的文件。这个例子
   达到与 BSD 的 -o 选项相同的效果,但更加灵活和
   便携式方式。

另一件可以尝试的事情是使用 -a 而不是 cat:

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

或两者的某种组合。

The man page for GNU xargs shows a similar command for emacs:

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

(in this command, the second "emacs" is the "dummy string" that wisbucky refers to in a comment to this answer)

and says this:

   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.

Another thing to try is using -a instead of cat:

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

or some combination of the two.

稚气少女 2024-10-03 14:11:55

如果您安装了 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 用于 xargs(如其他地方所述)仅适用于某些版本的 xargs(特别是它不适用于 GNU xargs)。

观看介绍视频,了解有关 GNU Parallel 的更多信息 http://www.youtube.com/watch?v =OpaiGYxkSuQ

If you have GNU Parallel http://www.gnu.org/software/parallel/ installed you should be able to do this:

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

In general this works too:

cat filelist | parallel -Xuj1 $EDITOR

in case you want to edit more than one file at a time (and you have set $EDITOR to your favorite editor).

-o for xargs (as mentioned elsewhere) only works for some versions of xargs (notably it does not work for GNU xargs).

Watch the intro video to learn more about GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ

九歌凝 2024-10-03 14:11:55

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

ls *.h | xargs vim

显然,这是 vim 的问题:

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

Interesting! I see the exact same behaviour on Mac as well, doing something as simple as:

ls *.h | xargs vim

Apparently, it is a problem with vim:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文