195

I like the watch command, but it has its limitations.

I'm curious to know whether I could mimic the functionality of watch with less. I'm mainly looking for the ability to scroll through my directory as it dynamically gets modified via a running script.

Zaid
  • 10,642
  • I am looking for tail -f foo.log | grep bar, and to be able to dynamically change the grep command with restarting the tail/grep pipeline. – Alexander Mills Sep 13 '18 at 23:56

12 Answers12

182

In less, you can type F (Shift+F) to keep reading at the end of a file (like tail -f); you can type :e and a file name to view a different file, but unfortunately, if you enter the name of the current file, less doesn't reload the file. However there's a trick to make it re-read the current file, suggested by sabgenton: type :e and enter the name of a non-existent file; that causes less to display an error message and then reload the current file.

If you're looking for an alternative to watch ls, here are a few:

  • Modern file managers (e.g. Nautilus, Thunar, Konqueror, Dolphin, Finder) refresh views in real time.
  • Emacs doesn't have real-time refresh, but with auto-revert-mode, it will reload the file or directory every 5 seconds (the delay is configurable).
  • Although w3m is primarily a web browser, it makes a passable directory and text file viewer. Press R to reload the (local) URL.
  • 15
    For me :e randomnamejkdlfjldf fails to load the non-existent filename then reloads back to the current file :D – sabgenton Mar 18 '16 at 10:36
  • 1
    @sabgenton Thanks, I didn't know that. That's a great trick. I added it to my answer, but you could post it as an answer of your own (which I hope Zaid would accept). – Gilles 'SO- stop being evil' Mar 18 '16 at 16:14
  • What if the file contents change but changes aren't necessarily appended. As in the file contents may be replaced completely, or partially. Does less +F deal with such a thing? – CMCDragonkai Apr 19 '16 at 09:01
  • 2
    @CMCDragonkai No, less +F only watches for appended content. Use :e nonexistentfile to re-read completely changed input. – Gilles 'SO- stop being evil' Apr 19 '16 at 11:08
  • 1
    Is there a command line flag for that? – CMCDragonkai Apr 19 '16 at 11:18
  • 1
    @CMCDragonkai No. If you want automatic refresh, I think you need a fancier tool like Emacs with autorevert mode, or else send the :e automatically (like http://askubuntu.com/questions/355301/terminal-web-browser-page-reload). – Gilles 'SO- stop being evil' Apr 19 '16 at 11:24
  • 1
    Turns out that vim has autoread and checktime. – CMCDragonkai Apr 19 '16 at 11:26
  • The answer from @destenson should also be added/linked to https://unix.stackexchange.com/a/330009/13676 This is the real answer, since it turns out that less also has a 'R' command to 'Refresh' the file. – Paul Wagland Apr 20 '17 at 08:42
  • 4
    @PaulWagland No, R doesn't reliably refresh the file. It refreshes the screen, and wipes some input buffers, but it doesn't actually reload data from the file in all circumstances (only if the file is large? I didn't dig deeply into the code). – Gilles 'SO- stop being evil' Apr 20 '17 at 09:53
  • @Gilles Ah. OK, the test that I was doing was indeed with a large (15Gb!!) file, so that might explain why I always saw the refresh. Thanks for the update. – Paul Wagland Apr 20 '17 at 09:55
  • 2
    I wish I could give you a +1 for every time I forget about this and find myself here again. :D – George Marian Jun 16 '17 at 01:17
  • This solution will work when R doesn't: https://unix.stackexchange.com/questions/4351/is-there-a-way-to-dynamically-refresh-the-less-command/445633#445633 – wisbucky Apr 17 '19 at 19:17
  • Sadly, this trick (:e gibberish) no longer seems to work. In less ver 487 on my Raspberry Pi, I pipe a ls -l to less, then I move one of the files in the listing. The display appears to refresh, but the file I moved is still in the listing. – Seamus Jul 18 '20 at 00:46
  • 1
    @Seamus You mean ls -l | less ? This has never worked and cannot possibly work. The ls command has already run and there is no instruction to run it again. The question was about re-reading a file. – Gilles 'SO- stop being evil' Jul 18 '20 at 13:58
  • @Gilles'SO-stopbeingevil': I did not know that - thanks. Why couldn't it work - are you saying that this intrinsically cannot be done? It can run other commands when command output is piped to it - e.g. search (?). I'm not suggesting that it should be done, but I don't understand why it "cannot be done". And what is the oft-repeated statement, "everything's a file"? I guess in this case, the file would need refreshing with another ls -l, but is that impossible? – Seamus Jul 18 '20 at 19:28
  • @Seamus less can run other commands, but here nothing is instructing it to. It's reading from a pipe and it doesn't know what is writing to the pipe. All it can do is keep reading from the pipe, but that does nothing since nothing is writing to the pipe anymore. – Gilles 'SO- stop being evil' Jul 19 '20 at 08:57
  • @Gilles'SO-stopbeingevil': Yeah, I got that - it didn't occur to me at first, but finally did while writing the last comment. My only point was that I can't see why it's impossible for less to learn how it was spawned - I was thinking of the history command specifically, but thought there must be other ways also. But you've indulged my curiosity long enough, so please don't feel compelled to reply. – Seamus Jul 19 '20 at 17:57
83

Shift+F will make less similar to the command tail -f. That is, it gets refreshed if more data is appended to the file.

SebMa
  • 2,149
balki
  • 4,407
  • 17
    Note that this only works for appends. If lines are removed or edited in-place, less won't show those changes. – Nathaniel M. Beaver Nov 30 '16 at 01:26
  • 2
    How do I stop following mode and re-enter scrollable mode? – Tom Hale Feb 09 '17 at 12:18
  • 4
  • 2
    balki My experience is that this kills the command piping the data if you are using $COMMAND | less. I wonder if there is a nice way around this? You can do stuff like $COMMAND > /tmp/file & less /tmp/file but that's not very nice. – Att Righ Jul 27 '18 at 11:13
  • 1
    @AttRigh I never killed my command (however i read logs of running commands this way, i don't pipe into less, technically) – jena Jan 11 '19 at 13:48
57

Simply type:

less +F filename

This emulates pressing "F" within the editor.

jhclark
  • 709
30

man pages can be very informative. Don't be intimidated by them. Among everything else, man less says you can use the R command to:

   R      Repaint the screen, discarding any buffered input.  Useful if the file is changing while it is being viewed.

(I realize this question is over 6 years old, but it comes up on google searches, so I'm not the only one that clicked the link to get here.)

  • 12
    This repaints the screen in case it was disrupted by output from another program. It doesn't consistently reload the file. I haven't dug deeply into the code to see what it does, experimentally short files don't get reloaded. I am definitely not intimidated by man pages and I say this description is poorly worded: “repaint” does not convey that input is re-read, and the actual behavior does not quite fit “useful if the file is changing” (maybe it's a bug? I don't know since I don't know what the command is supposed to do).. – Gilles 'SO- stop being evil' Apr 20 '17 at 09:51
  • I'm no expert, and haven't read less's source code either, but what it does is forget what it already knows about the file & reloads it, refreshing its output based on the input it reloads. The question reads "Is there a way to dynamically refresh the less command?" If I had read the question's explanation more thoroughly before answering, I might not have answered, since they go on to say they want "to scroll through my directory as it dynamically gets modified via a running script." less wouldn't be the right command for that. – Dennis Estenson Apr 21 '17 at 03:58
  • Works fine for me, even when using files 3 bytes long. I can't imagine why it wouldn't work for larger files too. – Addison Mar 22 '18 at 03:51
  • 3
    Great! For me it works for both short and long files. I just noticed two possible problems: 1. less did not reopen the file using its filename - i.e. when the inode of the file changed (like in overwriting the file using mv) then the old file content stayed (probably the old inode was reread) --- 2. The first displayed line probably starts at the same byte offset as in the original file content. So when the line lengths change the first displayed line could be incomplete and the displayed lines could move up / down. – pabouk - Ukraine stay strong Sep 13 '18 at 11:27
  • 3
    R doesn't always work. See https://unix.stackexchange.com/questions/4351/is-there-a-way-to-dynamically-refresh-the-less-command/445633#445633 – wisbucky Apr 17 '19 at 19:18
  • Like this trick. But as much effort as Q and rerun less. – Ronn Macc Jun 18 '20 at 01:50
  • Doesn't seem to work for me at all... (linux, less a file, modify using vi in another terminal)... – rogerdpack Oct 28 '20 at 15:16
  • This is better than G when you need to stay where you were initially. If I just want the end, then G is preferable. But this one is very useful. – akostadinov Dec 19 '23 at 20:53
12

R for repaint does not always reload the file.[1]

A workaround that always reloads the file is to press hq, which will open the Help page, then quit. It has a side effect of forcing the file to reload.


[1] Here are some examples of situations that R do and do not reload:

  • > and >> changes: DO get reloaded
  • sed -i, gEdit, TextEdit: DO NOT get reloaded
  • On Linux, vi changes: DO get reloaded
  • On Mac, vi changes: DO NOT get reloaded

I believe the difference comes down to whether the inode changes (you can check with ls -i foo.txt). If the inode changes, then R will not work.

wisbucky
  • 3,388
  • I really like the hq hack, but note that if you happen to be viewing the end of a file that gets shorter, less will fail out. (Really, if you happen to be seeked anywhere past the end of the new file) With one more key, you can avoid that crash: ghq. – carver Dec 10 '19 at 01:09
7

I normally just type G to tail the output on a one-time basis. I find it especially helpful over a a network file system like CIFS.

jorb
  • 143
  • This is more of an on-demand refresh of the file opened with less. In addition to jumping to the end of the file, it also reloads the file if it has changed. – jorb Jun 06 '17 at 13:23
  • 1
    Thanks. First time it didn't refresh for me, but now it seems to work properly. In the man it's not written that it refreshes the file. man less: 'G or > or ESC-> Go to line N in the file, default the end of the file.' I delete my old wrong comments here, sorry for them. – Yaroslav Nikitenko Jun 08 '17 at 13:56
  • 2
    BTW, what do you call a 'one-time basis'? The maintainer of less, Mark Nudelman, replied the following: "The G command does not normally force a re-read of the file like the R command does. It may seem do that if the end of the file has not yet been read when G is invoked, so that jumping to the end of the file must read the data there for the first time. For example, if you jump to the end with G, then jump back to the beginning with 1G, then another program modifies the data at the end of the file (without changing the length), " (cont) – Yaroslav Nikitenko Jun 12 '17 at 20:14
  • (cont) "then you jump to the end again with G, you will not see the modified data. But if you don't jump to the end and back to the beginning, then the first time you execute the G command it must read the data there for the first time, and of course it will see any modifications that have happened since less was first invoked. " – Yaroslav Nikitenko Jun 12 '17 at 20:14
  • 1
    In this case I mentioned it being a one-time refresh as opposed to a dynamic refresh, which is part of what the original question is asking. – jorb Jun 12 '17 at 20:31
5

The "F" key when running less will do a "follow" similar to tail -f, but I'm not sure if that will achieve what you're looking for here.

1

You can use vim to read the file then add the following mapping to your .vimrc file and you can easily reload a file with ,r:

let mapleader = ","
nnoremap <leader>r :edit <CR>

Note if you edited the file already, vim will complain. Just change to

let mapleader = ","
nnoremap <leader>r :edit! <CR>

To ignore changes.

puk
  • 333
  • They'll have to pry vim from your cold, dead hands. The context of the question is about less, but as someone with monomaniacal tendencies myself, I sympathise! – Benjamin R Oct 26 '18 at 16:05
1

You could pipe it to tail -f instead, it would result in you following the output. You'd be losing the ability to move (scroll) through your output though.

Gert
  • 9,994
1

I worked around this problem using a shell script that auto-reloads less on exit:

while true; do less -K file.txt || exit; done

With this script, I can hit q to reload the file, and CTRL+C to exit back to the bash shell. The CTRL+C behavior is enabled via the -K option. Your last search term will be preserved.

This can be further refactored by using the colon (:) to create an empty expression, via do : ...

while less -K file.txt; do : ; done

Drawbacks

The current viewing position will always be rest to line 0.

Practical Example using mintty

In my windows (GitBash) environment I set up a script that opens a new terminal window (mintty) for less-viewing a file:

lesswin() { mintty bash -c "while less -K \"$@\"; do : ; done;" & }
jstine
  • 111
0

I just found this thread like anyone else. I would like to add the solution of when you are already at the end of the file, using 'g' followed by 'G' will force a refresh of the file.

I ended up making a macro button for this in my terminal program (SecureCRT). The macro is simply 'gG'.

0

You could use the inotify-tools to watch for directory changes and rerun ls every time a file is written to:

inotifywait -mqe CLOSE_WRITE <directory-path> | while read; do clear; ls <directory-path>; done

inotifywait can also be used to watch an overwritten file:

inotifywait -mqe MODIFY <file-path> | while read; do clear; cat <file-path>; done
IngoMeyer
  • 113