After doing grep and passing it to vim then quitti

2019-07-27 04:28发布

问题:

I tried this just now:

grep -RlI "id=\"kw\"" * | xargs vim

That gave me 16 results. It opened the first result in Vim. I made my very first edit and hit :q since I didn't know the shortcut to jump to the next file.

It threw me back to the console ( I am SSHed in to a server ). My console is messed up now. Anything I type I can't see, and anytime I hit enter it seems like it processes the command but the display/view is screwed up so

[meder@linode] is tabbed in on my console, at least halfway. reset does nothing since it seems to have messed up my real console.


Can anyone offer a solution that doesn't have this same downside? Or can anyone provide an explanation for why :qing out of the very first file messed up my console?


Background information: My PC is Debian Ubuntu, I am SSHed into a RHEL box. The files I opened were text/ascii files phtml/php files and not some weird binary files with crazy characters in them.

Here's a screenshot of what happened

EDIT #1: I just typed reset again and it seemed to work. The first reset did not work I think because somehow the console inserted some whitespaceish character inside it? Anyways, I would like an explanation for this weird behaviour.

回答1:

Try:

vim -o `grep -RlI "id=\"kw\"" * `


回答2:

From the man page for xargs:

     Undefined behavior may occur if utility reads from the standard input.

That line isn't in the Linux man page but it is present on my Mac. If you want to run a program that you intend to read standard input, the usual linux version of xargs will need an argument to read its input from a file:

   OPTIONS
       --arg-file=file, -a file
              Read items from file instead of standard input.
              If you use this option, stdin remains unchanged
              when commands are run.  Otherwise, stdin is
              redirected from /dev/null.

Vim is intended to run with both standard input and standard output connected to real (a very rare case these days) or pseudo tty devices. Wierd things will happen if you upset this arrangement.

The fundamental problem with your command was that, with standard input redirected to the pipe, xargs had no way to run a vim with a "normal" standard input. So the vim mode changes and command input were not what you expected.

You can probably fix this by typing a return, a tilde, and a period. This will force your ssh session closed from your end, you can then ssh in again, and run "ps" to check for anything left hung in the background that you should kill(1).



回答3:

You can use :next or :n to get to the next file to edit. You can also use vim -o to open up all the matching files in different windows in Vim.

Not sure why your console is messed up though. I tried using your command and my console was fine.



回答4:

Console options are set by stty, so you may want to save its options to a bash variable and restore them after vim exits, like this:

function vim()
{
    STTYOPTS="$(stty --save)"
    vim "$@"
    stty "${STTYOPTS}"
}

But it is probably the better way to use zsh for this task: if you put the only line ttyctl -f into your ~/.zshrc, then zsh will automatically restore terminal options after program exits. ttyctl is a zsh builtin, so you cannot use it from bash.



回答5:

Other folks covered what happened and what to do about it. As to why, the answer to that probably lies in what input Vim received from the xargs command and tried to execute as if that input came from a terminal. I don't know how to talk terminal, but you can imagine that Vim got some strange commands that crashed it or told it to quit. Similarly unpredictable things happen when you cat a binary file.

Anway, I have another idea. Have you tried using vimgrep to browse a list of files matching a pattern?

:vimgrep /id="kw"/ *
:copen

This greps for id="kw" in all files in the current directory. :copen opens up a window with a list of matches. You can browse that list, clicking enter to jump to a file position.

For more information, see

:help grep
:help :vimgrep
:help :copen
:help quickfix

If you really need that -I option, see

:help :grep
:help 'grepprg'

See also: Vim: Warning: Input is not from a terminal



回答6:

Try to use ... | xargs sh -c '...' and then read from the controlling terminal device /dev/tty.

echo ~/.profile ~/.bashrc | xargs sh -c 'vim "$@" </dev/tty' dummy_script_name

# based on a tip by Laszlo Ersek on http://unix.derkeiler.com/Newsgroups/comp.unix.programmer/2010-03/msg00051.html
#find . -maxdepth 1 -type f | xargs sh -c 'rm -i "$@" </dev/tty' dummy_script_name