My question is similar to this how to monitor a text file in realtime
but I want to do it in vim. I know I can read an opened file use tail -f sample.xml
file, and when new content is written to the file, it'll also write the new content to my screen. Can I have vim automatically fill the new data when a file is updated?
-
Related questions: [filesystem - How can I make Vim autoread a file while it doesn't have focus? - Vi and Vim Stack Exchange](https://vi.stackexchange.com/questions/2702/how-can-i-make-vim-autoread-a-file-while-it-doesnt-have-focus) – user202729 Dec 09 '21 at 15:46
10 Answers
You can :set autoread
so that vim reads the file when it changes. However (depending on your platform), you have to give it focus.
From the help:
When a file has been detected to have been changed outside of Vim and it has not been changed inside of Vim, automatically read it again. When the file has been deleted this is not done.

- 127,331
- 53
- 180
- 211
-
6Thanks for the hint! This looks pretty promising, but it doesn't work on my system :( I'm using Mac10.6.2 iTerm with vim version 7.2.303 compiled with MacVim. Any additional comment I can try? – Patrick Jan 29 '10 at 04:05
-
erm, that's pretty weird. are you using the macvim gui or the terminal version? it works for me with macvim gui downloaded precompiled. (I do have to click on the app to give it focus though, as I mentioned.) – Peter Jan 29 '10 at 04:13
-
1I was testing in terminal, after I used gvim (MacVim GUI) the function began to work! As you mentioned though, I need to focus gvim to update the content. Do you have any trick to update it even without focusing? Thanks for your help again. – Patrick Jan 29 '10 at 04:20
-
3I don't know a solution to that, unfortunately. I'd be stunned if vim could do it without the change of focus - it would require vim to poll the filesystem to see when it changes. I think you'd need a plugin for that. – Peter Jan 29 '10 at 06:19
-
2@Peter I [made such a plugin](http://www.vim.org/scripts/script.php?script_id=5206) a while ago. Also see [this question and my answer to it](http://vi.stackexchange.com/q/2702/51). for more details as to how `autoread` works and its limitations. – Martin Tournoij Mar 03 '16 at 20:08
-
This answer didn't work for me but the plugin by @Carpetsmoker works great! Using it alongside `autocmd VimEnter * Autoread` in .vimrc – Cibin Joseph Mar 18 '17 at 19:45
Don't know about automatically, but you can type:
:e!
to reload the file

- 26,717
- 34
- 141
- 196
-
Although this approach does not auto update the content, it does display the updated content. Thanks for your answer! – Patrick Jan 29 '10 at 04:07
Put the following in your .vimrc
:
" check one time after 4s of inactivity in normal mode set autoread au CursorHold * checktime

- 709
- 6
- 7
-
1Great! Works well, even with a warning if you have changed that file since last reloading. – Joey.Z Jul 02 '14 at 10:58
-
2
-
5The "every 4 seconds" isn't true. This will only check *one* time after 4s of inactivity in normal mode. So if you don't do anything in another buffer for a long time, it won't be updated, but it would if you just move the cursor and wait 4s. Another option is to manually call ":checktime" to update (after setting autoread). Unfortunately there doesn't seem to be any sort of polling support in vim, so there is no true answer to the OPs question. – David Ljung Madison Stellar Feb 07 '15 at 21:28
-
1Just came across this. If you change checktime to call a custom function and add " call feedkeys("lh")" to the end of the function then it will fire every 4 seconds. – flukus Mar 12 '16 at 23:06
-
@DavidLjungMadison you are right, I am going to edit the post to avoid this mistake – Phan Hai Quang Sep 04 '16 at 06:51
-
You'll also want `set belloff=all`, or vim will beep every four seconds if the cursor is in a blank line. – Wolfram Rösler Jul 20 '22 at 07:27
like @flukus said in a comment to a previous answer you can call feedkeys["lh"]
(it moves the cursor to the right and back to the left, which normaly doesn't do harm when viewing a log file)
So, if you combine the rest of the answer you have a oneliner you can run from ex (whithin vim) when needed:
:set autoread | au CursorHold * checktime | call feedkeys("lh")
***(if you would want to jump (nearly) to the end of the file, just use "G" instead of "lh" with feedkeys)***
Explanation:
- autoread: reads the file when changed from the outside (but it doesnt work on its own, there is no internal timer or something like that. It will only read the file when vim does an action, like a command in ex
:!
- CursorHold * checktime: when the cursor isn't moved by the user for the time specified in 'updatetime' (which is 4000 miliseconds by default) checktime is executed, which checks for changes from outside the file
- call feedkeys("lh"): the cursor is moved once, right and back left. and then nothing happens (... which means, that CursorHold is triggered, which means we have a loop)
Additionally you can :set syntax=logtalk
to color the log
To stop the scrolling when using call feedkeys("G")
, execute :set noautoread
- now vim will tell, that the file was change ans ask if one wants to read the changes or not)
(Does this have any sideeffects?)
Edit: I see one side-effect: if one uses "G" as the feedkey, it will scroll down every currently opened buffer?! So, it's not possible to work in the left buffer of a splittet window while having the right buffer scroll down a logfile automatically
Edit2: Another side effect is that when you enter the command line window(by using q:
) an error message always pops up.

- 15
- 5

- 2,366
- 1
- 24
- 27
-
how to modify the above command to check for and change in every 1 second instead of 4 seconds – Udesh Feb 18 '22 at 02:50
-
Stick this in your .vimrc and it should work like a boss. (Taken from: http://vim.wikia.com/wiki/Have_Vim_check_automatically_if_the_file_has_changed_externally)
" Function to Watch for changes if buffer changed on disk
function! WatchForChanges(bufname, ...)
" Figure out which options are in effect
if a:bufname == '*'
let id = 'WatchForChanges'.'AnyBuffer'
" If you try to do checktime *, you'll get E93: More than one match for * is given
let bufspec = ''
else
if bufnr(a:bufname) == -1
echoerr "Buffer " . a:bufname . " doesn't exist"
return
end
let id = 'WatchForChanges'.bufnr(a:bufname)
let bufspec = a:bufname
end
if len(a:000) == 0
let options = {}
else
if type(a:1) == type({})
let options = a:1
else
echoerr "Argument must be a Dict"
end
end
let autoread = has_key(options, 'autoread') ? options['autoread'] : 0
let toggle = has_key(options, 'toggle') ? options['toggle'] : 0
let disable = has_key(options, 'disable') ? options['disable'] : 0
let more_events = has_key(options, 'more_events') ? options['more_events'] : 1
let while_in_this_buffer_only = has_key(options, 'while_in_this_buffer_only') ? options['while_in_this_buffer_only'] : 0
if while_in_this_buffer_only
let event_bufspec = a:bufname
else
let event_bufspec = '*'
end
let reg_saved = @"
"let autoread_saved = &autoread
let msg = "\n"
" Check to see if the autocommand already exists
redir @"
silent! exec 'au '.id
redir END
let l:defined = (@" !~ 'E216: No such group or event:')
" If not yet defined...
if !l:defined
if l:autoread
let msg = msg . 'Autoread enabled - '
if a:bufname == '*'
set autoread
else
setlocal autoread
end
end
silent! exec 'augroup '.id
if a:bufname != '*'
"exec "au BufDelete ".a:bufname . " :silent! au! ".id . " | silent! augroup! ".id
"exec "au BufDelete ".a:bufname . " :echomsg 'Removing autocommands for ".id."' | au! ".id . " | augroup! ".id
exec "au BufDelete ".a:bufname . " execute 'au! ".id."' | execute 'augroup! ".id."'"
end
exec "au BufEnter ".event_bufspec . " :checktime ".bufspec
exec "au CursorHold ".event_bufspec . " :checktime ".bufspec
exec "au CursorHoldI ".event_bufspec . " :checktime ".bufspec
" The following events might slow things down so we provide a way to disable them...
" vim docs warn:
" Careful: Don't do anything that the user does
" not expect or that is slow.
if more_events
exec "au CursorMoved ".event_bufspec . " :checktime ".bufspec
exec "au CursorMovedI ".event_bufspec . " :checktime ".bufspec
end
augroup END
let msg = msg . 'Now watching ' . bufspec . ' for external updates...'
end
" If they want to disable it, or it is defined and they want to toggle it,
if l:disable || (l:toggle && l:defined)
if l:autoread
let msg = msg . 'Autoread disabled - '
if a:bufname == '*'
set noautoread
else
setlocal noautoread
end
end
" Using an autogroup allows us to remove it easily with the following
" command. If we do not use an autogroup, we cannot remove this
" single :checktime command
" augroup! checkforupdates
silent! exec 'au! '.id
silent! exec 'augroup! '.id
let msg = msg . 'No longer watching ' . bufspec . ' for external updates.'
elseif l:defined
let msg = msg . 'Already watching ' . bufspec . ' for external updates'
end
echo msg
let @"=reg_saved
endfunction
let autoreadargs={'autoread':1}
execute WatchForChanges("*",autoreadargs)
-
1This is the preferred answer to address terminal autoread shortcomings. – mcanfield Sep 18 '15 at 21:07
-
3@mcanfield No it isn't as this still doesn't "watch for changes". You **still** need to have Vim active and it is **still** polling (not watching) on a limited set of events. `CursorHold` is run *once*. So if you go off and have a coffee, or are doing something in another Window it will **not** update. – Martin Tournoij Mar 03 '16 at 20:12
-
4That script is also bundled as a Vim plugin: [vim-autoread](https://github.com/djoshea/vim-autoread). – stephen.hanson Sep 11 '18 at 19:43
-
1@stephen.hanson Thanks for the link, that plugin is working well for me! – Tropilio Apr 10 '20 at 08:48
There is a plugin also:
https://github.com/djoshea/vim-autoread
This was the only way I could make this work on OSX.

- 302
- 2
- 11
If unix + neovim
:term tail -f <filename>
Obviously this won't work for everyone, but it's how I do it.

- 15,939
- 6
- 34
- 37
-
All this does is open a terminal window within vim, and uses the original command. That doesn't let you use any of vim's features with the file - no syntax highlighting, folding, navigation etc etc – Len Jan 13 '22 at 00:58
To enable reloading if you open a specific file, you can add this to your .vimrc
and use a modeline like vim: set ft+=.watch:
. It takes advantage of the feature to set multiple filetypes for a buffer (see below):
vim9script
command WatchFiles {
autocmd! AUWatchFile FocusGained,VimResume,BufEnter,WinEnter,CursorHold * checktime
autocmd! AUWatchFile BufEnter,InsertEnter,CursorHold,CursorHoldI <buffer> checktime
setlocal autoread
checktime
}
command UnwatchFiles {
autocmd! AUWatchFile
set autoread<
}
# To enable this, you may use e.g. a modeline: `vim: set ft+=.watch`
def WatchAutomatically()
# Check if the "list" of filetypes (a dot separated string) contains 'watch'.
if -1 != match(&filetype, "\\(^\\|\\.\\)watch\\($\\|\\.\\)")
WatchFiles
endif
enddef
augroup AUWatchFile | augroup END
autocmd BufWinEnter * call WatchAutomatically()
More details
You are able to set multiple filetypes separated by .
:
When a dot appears in the value then this separates two filetype names. Example: /* vim: set filetype=c.doxygen : */ ~
See :help 'filetype'
.
Keep in mind that you should manipulate the filetype first and set additional options after that in the modeline. Otherwise these options may be overridden by the settings specific for the filetype.
Btw, the above is a Vim9 script (which I discovered today). Translating it back to a good-old Vim script is trivial:
- Use
"
for comments. - Transform multi-line commands like this:
command UnwatchFiles \ autocmd! AUWatchFile \ | set autoread<
- Remove the
vim9script
line.
See :help Vim9-script
for details.
Shortcomings
- Reloading is not limited to the buffer which contains the modeline. You may disable it again with
:UnwatchFiles
. - It is still dump polling.

- 809
- 9
- 24
VIM will warn you when a file has been updated so that you don't overwrite changes that have been made since you opened it. It will prompt you at that point to reload the file.

- 7,225
- 3
- 39
- 37
-
2Thanks for your answer, but vim did not warn me when the file was changed in my system :( – Patrick Jan 29 '10 at 04:06