I am trying to output the contents of a file opened in vim ex mode to stdout.

vi -es +'%write !tee' +'q' ./testfile

Unfortunately, it does not write anything, although if I open the file in ex mode, like this:

vi -e ./testfile

and issue the same command:

:%write !tee

then the file contents are shown.

Of course, there are other vi commands I would issue before writing to stdout but first I would like to make this one work.

Note: I also tried the print and list commands, however, they replace tabs (and I want to keep them as they are in the file).

  • You might find this interesting: github.com/DJMcMayhem/V. Though they're using %p there, so I think it has the shortcoming that tabs won't work as you mentioned... – filbranden Mar 14 '20 at 14:29

This is a hack but if a direct solution can't be found perhaps it will do (I have an idea of how to do it purely with vim but need to try it later).

Try the print command :[range][p]rint [flags] with l as a flag. This will replace tabs with ^I (two characters). Then use sed to replace with actual tabs.

For example, to output an entire file:

 vim -e -s -c'%p l|q!' foo.txt | sed 's/^I/\t/g'

(The -s (silent mode) flag keeps the screen from jumping.)

Update: Okay, I'm not seeing any simple way to do this. Almost everything strips the tabs. Best I can come up with is still hacky but at least it's pure vim. It'll only work with *nix systems with the special file /dev/stdout.

You need a custom function. One approach is to put it in a file and source it. Here's the function:

func! DumpToStdout()
    redi! > /dev/stdout
    for line in getline(1, '$')
        echo line
    redi END

If I put it in, say, dump.vim then the vim/ex command is

vim -e -S dump.vim -s -c 'call DumpToStdout()' -c 'q!' foo.txt

(Actually, you could probably cram the function contents into the command line and avoid the need for the extra file but...yuck.)

  • I wonder if you could use vis instead of sed for the first attempt? – D. Ben Knoble Mar 15 '20 at 13:04
  • vis? What is that? – B Layer Mar 15 '20 at 14:03
  • Perhaps I meant unvis; vis and unvis are a pair of programs designed around cat -v; the first visualizes unprintables in a text stream, while the second restores the actual unprintables. – D. Ben Knoble Mar 15 '20 at 14:05
  • 1
    I'm know linux command line quite well and know about cat's -v and -t/-T but I don't recall hearing about vis/unvis. Is it gnu or perhaps a different user land flavor? – B Layer Mar 15 '20 at 14:09
  • I only just read about them (i think in fred brooks’ no silver bullet, but maybe not—certainly a paper/essay on good design). I found them happily on my mac, but im not sure if they came from coreutils or moreutils or what. Ill look later. – D. Ben Knoble Mar 15 '20 at 14:11

If /dev/stdout is available on your system, you can try

vi -es +'%write! /dev/stdout' +'q' ./testfile

On many modern Linux systems, /dev/stdout is a symlink to file descriptor 1 of the current process (/proc/self/fd/1, aka stdout). If you are on Linux but don't have /dev/stdout, then there is still a possibility that this will work:

vi -es +'%write! /proc/self/fd/1' +'q' ./testfile
  • This one works, too, thanks. – z32a7ul May 30 '20 at 5:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.