通过调用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的参数。