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, 2020 at 14:29

2 Answers 2


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, 2020 at 13:04
  • vis? What is that?
    – B Layer
    Mar 15, 2020 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, 2020 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, 2020 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, 2020 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, 2020 at 5:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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