通过调用vim
时find | xargs
,如下所示:
find . -name "*.txt" | xargs vim
您收到有关的警告
Input is not from a terminal
然后终端的行为几乎崩溃。这是为什么?
grep -l .. | xargs vim
产生警告,为什么?在Unix SE
通过调用vim
时find | xargs
,如下所示:
find . -name "*.txt" | xargs vim
您收到有关的警告
Input is not from a terminal
然后终端的行为几乎崩溃。这是为什么?
grep -l .. | xargs vim
产生警告,为什么?在Unix SE
Answers:
通过调用程序时xargs
,程序的stdin(标准输入)指向/dev/null
。(由于xargs不知道原始的 stdin,所以它做的第二件事就是。)
$ true | xargs filan -s 0 chrdev / dev /空 1 tty / dev / pts / 1 2 tty / dev / pts / 1 $ true | xargs ls -l / dev / fd /
Vim期望其stdin与它的控制终端相同,并直接在stdin上执行各种与终端相关的ioctl。完成处理/dev/null
(或任何非tty文件描述符)后,这些ioctl将变得毫无意义,并返回ENOTTY,该提示将被静默忽略。
我的一个更具体的原因是猜测:启动时,Vim会读取并记住旧的终端设置,并在退出时将其恢复。在我们的情况下,当为非tty fd(文件描述符)请求“旧设置”时,Vim会收到所有空值,并且禁用所有选项,并且不小心将其设置为您的终端。
您可以通过运行vim < /dev/null
,退出它然后运行来查看此内容stty
,这将输出很多<undef>
s。在Linux上,运行stty sane
将再次使终端中使用(虽然它会失去这样的选择iutf8
,可能导致小烦恼更高版本)。
您可以将其视为Vim中的错误,因为它可以打开/dev/tty
以进行终端控制,但不能打开。(在启动过程中的某个时候,Vim将其stderr复制到stdin,这使它可以从为写入而打开的fd中读取输入命令,但即使这样做还不够早,也是如此。)
stty sane
reset
代替,stty sane
之后它可以正常工作。
(从grawity的解释,那下面就xargs
点stdin
到/dev/null
。)
该解决方案针对此问题是将增加-o
参数xargs
。来自man xargs
:
-o
/dev/tty
在执行命令之前,请像子进程 一样重新打开stdin 。如果要xargs
运行交互式应用程序,这将很有用。
因此,以下代码行应为您工作:
找 。名称“ * .txt” | xargs -o vim
GNU xargs自2017年发布以来就支持此扩展(带有长选项名称--open-tty
)。
对于旧版本或其他版本的xargs,可以显式传递/dev/tty
以解决问题:
find . -name "*.txt" | xargs bash -c '</dev/tty vim "$@"' ignoreme
(ignoreme
那里要占用$ 0,因此$ @是xargs的所有参数。)
$@
似乎没有正确翻译参数。
function vimin () { xargs sh -c 'vim "$@" < /dev/tty' vim; }
ignoreme
字符串的详细说明,请参见vi.stackexchange.com/a/17813
The -J, -o, -P and -R options are non-standard FreeBSD extensions which may not be available on other operating systems.
(对我而言,它在macOS上不可用,因为我是从homebrew(GNU版本)安装xargs的)
最简单的方法:
vim $(find . -name "*foo*")
如果在find上使用-exec选项,而不是通过管道传递到xargs,它应该可以正常工作。
find . -type f -name filename.txt -exec vi {} +
+
(而不是“通常的” \;
)将所有找到的文件放入一个 Vim会话中-我一直忘了这个选择。您当然是对的,为此+1。我vim $(find ...)
只是出于习惯而使用。但是,我实际上是在问为什么管道操作会拧紧端子,而grawless则用他的解释来说明这一点。
改用GNU Parallel:
find . -name "*.txt" | parallel -j1 --tty vim
或者,如果您想一次打开所有文件:
find . -name "*.txt" | parallel -Xj1 --tty vim
它甚至可以正确处理文件名,例如:
My brother's 12" records.txt
观看介绍性视频以了解更多信息:http : //www.youtube.com/watch?v=OpaiGYxkSuQ
vim $(find . -name "*.txt")
更简单,您可以一次打开所有文件。
find | xargs
并$(find)
会在文件名称空间大的问题。
$IFS
,-print0
和东西,然后你离开一个一次性的命令行解决方案的领域,并达到了一个点,你应该拿出一个剧本......还有就是为什么在文件名中的空格气馁的理由。
也许不是最好的,但这里是我使用的脚本(名为vim-open
):
#!/usr/bin/env ruby
require 'shellwords'
inputs = (ARGV + (STDIN.tty? ? [] : STDIN.to_a)).map(&:strip)
exec("</dev/tty vim #{inputs.flatten.shelljoin}")
将与vim-open a b c
和ls | vim-open
例如
find
或完全不执行xargs
。打开不带参数的vim,然后:args **/*.txt<CR>
从编辑器内部运行以设置vim的参数。