I have a file mk.out that contains ANSI codes, which can be cleaned up by opening it in Vim and issuing:

:term cat % " Interpret codes in new buffer
:only       " Close source buffer `mk.out`
:w! mk.out  " Overwrite `mk.out` with cleaned up text

This works fine, but problems arose when I tried to automate this:

vim -c ":term cat %" -c ":only" -c ":w! mk.out" mk.out

I am perplexed by the fact that this results in an empty buffer for cleaned up code and for mk.out. If I remove the command to overwrite mk.out, however, the new buffer ends up still containing the cleaned up text, and I can manually issue the overwrite command.

I also tried overwriting to a different file mk.cln (cln is for clean). In contrast to the above, the new buffer for the clean text doesn't mysteriously become empty (good), but the written file mk.cln is still empty:

vim -c ":term cat %" -c ":only" -c ":w! mk.cln" mk.out

This is regardless of whether the "bang" ! is present in the write command. As expected, mk.out is not disturbed. To rule out problems from prompting to overwrite mk.cln, I ensured that mk.cln did not exist beforehand.

For :term's new buffer, what would cause the :write command to write an empty file when submitted via Vim's -c switch, but not when issued interactively?

Other contextual details

Writing a new file from an existing file works, but the ANSI codes are not cleaned up:

vim -c ":w! mk.cln" mk.out

I realize that I need :wq, but I'm just trying to troubleshoot for now.

Vim version

VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Mar 30 2020 21:51:17)
Included patches: 1-486
Modified by <[email protected]>
Compiled by <[email protected]>
Huge version with GTK3 GUI.  Features included (+) or not (-):
+acl               -farsi             -mouse_sysmouse    -tag_old_static
+arabic            +file_in_path      +mouse_urxvt       -tag_any_white
+autocmd           +find_in_path      +mouse_xterm       -tcl
+autochdir         +float             +multi_byte        +termguicolors
-autoservername    +folding           +multi_lang        +terminal
+balloon_eval      -footer            -mzscheme          +terminfo
+balloon_eval_term +fork()            +netbeans_intg     +termresponse
+browse            +gettext           +num64             +textobjects
++builtin_terms    -hangul_input      +packages          +textprop
+byte_offset       +iconv             +path_extra        +timers
+channel           +insert_expand     +perl/dyn          +title
+cindent           +job               +persistent_undo   +toolbar
+clientserver      +jumplist          +popupwin          +user_commands
+clipboard         +keymap            +postscript        +vartabs
+cmdline_compl     +lambda            +printer           +vertsplit
+cmdline_hist      +langmap           +profile           +virtualedit
+cmdline_info      +libcall           +python/dyn        +visual
+comments          +linebreak         +python3/dyn       +visualextra
+conceal           +lispindent        +quickfix          +viminfo
+cryptv            +listcmds          +reltime           +vreplace
+cscope            +localmap          +rightleft         +wildignore
+cursorbind        +lua/dyn           +ruby/dyn          +wildmenu
+cursorshape       +menu              +scrollbind        +windows
+dialog_con_gui    +mksession         +signs             +writebackup
+diff              +modify_fname      +smartindent       +X11
+digraphs          +mouse             +sound             -xfontset
+dnd               +mouseshape        +spell             +xim
-ebcdic            +mouse_dec         +startuptime       +xpm
+emacs_tags        -mouse_gpm         +statusline        +xsmp_interact
+eval              -mouse_jsbterm     -sun_workshop      +xterm_clipboard
+ex_extra          +mouse_netterm     +syntax            -xterm_save
+extra_search      +mouse_sgr         +tag_binary        
   system vimrc file: "/etc/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "/etc/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/etc"
 f-b for $VIMRUNTIME: "/usr/share/vim/vim82"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK  -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/uuid -I/usr/include/harfbuzz -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -D_REENTRANT    -ggdb -O2 -pipe -Wall -Werror=format-security -fstack-protector-strong --param=ssp-buffer-size=4 -fdebug-prefix-map=/usr/src/ports/vim/vim-8.2.0486-1.x86_64/build=/usr/src/debug/vim-8.2.0486-1 -fdebug-prefix-map=/usr/src/ports/vim/vim-8.2.0486-1.x86_64/src/vim-8.2.0486=/usr/src/debug/vim-8.2.0486-1 -fstack-protector-strong -D_REENTRANT  -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1       
Linking: gcc   -L. -fstack-protector-strong  -L/usr/local/lib -Wl,--as-needed -o vim.exe   -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lintl  -lSM -lICE -lXpm -lXt -lX11 -lXdmcp -lSM -lICE  -lm    -lncursesw -lcanberra  -liconv -lacl -lattr -lintl   -Wl,--enable-auto-import -Wl,--export-all-symbols -Wl,--enable-auto-image-base -fstack-protector-strong  -L/usr/lib/perl5/5.30/x86_64-cygwin-threads/CORE -lperl -lpthread -ldl -lcrypt        
  • I wonder if %!cat would work instead of the terminal emulator?
    – D. Ben Knoble
    Sep 8, 2020 at 13:53
  • @D. Ben Knoble: Sorry, I only saw this now. I gave :%!cat a shot, but it preserved the ANSI codes rather than removing them (the latter being the objective). Sep 19, 2020 at 16:05

1 Answer 1


For :term's new buffer, what would cause the :write command to write an empty file when submitted via Vim's -c switch, but not when issued interactively?

You probably need to wait for pending updates. If so, you need term_wait().

Try this shell command:

vim -Nu NONE -i NONE -U NONE +'term cat %' +'call term_wait(bufnr("")) | bw! # | w! mk.out | qa!' mk.out

If it doesn't work, try to increase the waiting time:

vim -Nu NONE -i NONE -U NONE +'term cat %' +'call term_wait(bufnr(""), 100) | bw! # | w! mk.out | qa!' mk.out
                                                                       wait 100ms instead of 10

See :h term_wait().

If term_wait doesn't work, success has been had in at least the OP's case by replacing call term_wait(bufnr(""), xxx ) with sleep xxx m, where xxx is the wait time in milliseconds (500 worked for the OP). The final command can then be shortened to

`vim -Nu NONE -i NONE -U NONE +':term cat mk.out' +'sleep 500 m | silent! w! mk.out | qa'`.
  • I tried your 2nd code pattern with 500ms, but everything after physical line 4 is gone in the overwritten mk.out. I experimented with writing to mk.cln: vim -c ":term cat %" -c 'call bufnr("")->term_wait(500)' -c ":only" -c ":w! mk.cln" mk.out. In this case, mk.out contains the full unclean file while mk.cln contains the top 4 lines. Very odd. Sep 8, 2020 at 0:50
  • It works for me when mk.out contains this text.
    – user938271
    Sep 8, 2020 at 1:00
  • I just saved your test file and tried your 2nd code pattern with 500ms. The resulting mk.out is an empty file.....thanks for your help. I'm going to try messing around to see if I can get an idea of what's going wrong. If I don't figure out within a certain amount of time, I will have to manually intervene in every cleanup. Sep 8, 2020 at 1:05
  • I'm not sure why term_wait didn't work, but sleep seemed to have worked: vim +":term cat %" +"sleep 500 m | bw! # | w! mk.out | qa" mk.out. Sep 8, 2020 at 1:43
  • 1
    In the script containing the Vim command, Bash apparently won't allow both switches simultaneously, so I tried each in succession, with the same result. I fell back to sleep rather than term_wait. The final version "boldly" cuts out mk.cln and so far works with my small mk.out: vim -Nu NONE -i NONE -U NONE +':term cat mk.out' +'sleep 500 m | silent! w! mk.out | qa'. Thanks so much for the investigation that you've done. Sep 8, 2020 at 15:35

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.