- View and Follow the End of Text Files with tail
- What is tail?
- Syntax and Basic Usage
- Control the Length of tail Output
- Follow Mode
- Filter with grep
- display filename followed by content without interaction
- 4 Answers 4
- how to continuously display a file of its last several lines of contents
- 6 Answers 6
- How to ‘Follow’ a File in Linux? Grep? Pipe? WGET Etc
View and Follow the End of Text Files with tail
Estamos traduciendo nuestros guías y tutoriales al Español. Es posible que usted esté viendo una traducción generada automáticamente. Estamos trabajando con traductores profesionales para verificar las traducciones de nuestro sitio web. Este proyecto es un trabajo en curso.
What is tail?
The tail command is a core Linux utility used to view the end of text files. You can also use follow mode to see new lines as they’re added to a file in real time. tail is similar to the head utility, used for viewing the beginning of files.
Syntax and Basic Usage
Tail uses the following basic syntax:
This will print the last ten lines of example.txt to standard output on the terminal. tail is useful for reading files such as logs, where new content is appended to the end of the file.
To view multiple files, specify their names as additional arguments or use a wildcard:
tail example.txt example2.txt
View the end of all .log files in a directory:
Control the Length of tail Output
By default, tail will output the final ten lines of a file. To view more or fewer than ten lines, use the -n [number] option to control the number of lines that the tail command prints:
Line 6 Line 7 Line 8 Line 9 Line 10
Follow Mode
With the -f option, tail operates in follow mode. Here, tail prints the final lines of a file, then watches for new additions to the end of the file. When new lines are added they are printed to the terminal, giving you a live feed of the end of the file.
tail will continue to follow a file until the user sends a break (e.g. Control+c ) to the terminal. Additionally, if the file is deleted or renamed, tail -f will fail. Use the -F option to force tail to follow file names rather than file objects. This can prevent problems with log rotation and other programs that may alter file names.
Follow mode is very useful when troubleshooting issues because it allows you to watch logs in real time.
Filter with grep
tail can be combined with grep to filter the contents of a log file in real time. You can use this to track specific types of errors, such as 404 responses from an Apache web server:
tail -F /var/log/apache2/access.log | grep "404"
This page was originally published on Monday, November 29, 2010.
display filename followed by content without interaction
My program writes it state to few files every 30 seconds or so (overwrites) and I would like to look at them with the filenames displayed like «more» does. Like:
$ echo 1234 > test00 $ echo 5678 > test01 $ ls test00 test01 $ more * . test00 . 1234 . test01 . 5678
- What I want is the filenames before content in some way
- I tried «tail», but have to Ctrl + C , Can write a small program but I’m wondering if any standard unix program can do this ( display name of file, followed by content of file ) without further user interaction as with «more»
You had to ctrl-c? Just do tail without -f . It will display the last 10 lines in each file and the filenames.
4 Answers 4
If the output from more is acceptable as it is, just pipe it through cat :
That will do away with the «more» prompts.
Or you can get a bit more control over the display using printf in a one-liner:
for fn in *; do printf ". \n$fn\n. \n"; cat "$fn"; done
for fn in $*; do printf "vvvvvvvvvv\n$fn\n^^^^^^^^^^\n" cat "$fn" done
head and tail are both spec’d to display the first/last ten lines of a file by default — but if called w/ multiple arguments will do that for all and display the filenames for each. And, of course, for each, you can use the -n[num] argument to specify a number of lines other than the default ten that you would like to display. I assume your CTRL-C problem was related to the -f option — which would instruct tail to follow a file — you probably should just leave that out.
Another thing you might do — which will result in output a little different than in the question, but which you might still like, is.
grep is also spec’d to display the filename for its matches when it is given multiple filename arguments — but grep does it at the head of every line. Like
seq 10 >nums.txt; grep -F '' /dev/null nums.txt
nums.txt:1 nums.txt:2 nums.txt:3 nums.txt:4 nums.txt:5 nums.txt:6 nums.txt:7 nums.txt:8 nums.txt:9 nums.txt:10
. and highlighted on my terminal. The /dev/null thing is just a little trick to force the multiple file arg behavior even when working with only a single file, and grep -F » matches every line — even blank ones.
And here’s head /dev/null nums.txt :
tail ‘s output is identical in this case — but, again, both utilities only print so many lines of a file.
With the latest version of GNU sed you can use the F command like:
. or if you wanted a little border around the filename.
sed -se '1!b;i\\n---' -e 'F;i\---\n' nums.txt
--- nums.txt --- 1 2 3 4 5 6 7 8 9 10
Or if you wanted to get adventurous you could do.
tar -c ./*files | tr -s \\0 | cut -d '' -f1,2,13 | tr '\0' '\n'
. but that’s probably not practical.
how to continuously display a file of its last several lines of contents
I don’t think this could be done by simple shell commands. correct me if I am wrong. You are asking split the screen into two parts, above part shows the fixed 2 lines (newly first added 2 lines in that session), and down part shows sth like tail -f. it would look a bit like top command.. not in place changing but scrolling.
6 Answers 6
I use this function all the time to monitor a log file in another terminal window.
I recommend taking it a step forward to look for particular text in the log. Great if you are only interested in seeing some particular entry being written to the file.
This will update every 2 seconds rather than whenever data is written to the file, but perhaps that’s adequate:
watch 'head -n 2 job.sta; tail job.sta'
I tried and tested this is the best answer to suit my purpose. Many thanks. Also thanks to all the other responses. I also much appreciate your help.
Hi, Bro, I’ve got a new question based on your best answer. How can I write a customized command, like watch2. It runs as follows: $>watch2 job.sta So, it will get the filename from the command line arguments. I’ve tried much. But I am so pissed by the quote symbols. Do you have any light to shed?
You can use screen to simulate the expected behaviour:
- Run screen , press Space .
- Press Ctrl + a followed by S to split the screen.
- Resize the top window by pressing Ctrl + a followed by :resize 4 .
- In the prompt in the top window, enter head -n2 file .
- Move to the bottom window by pressing Ctrl + a followed by Tab .
- Start a new screen session by pressing Ctrl + a followed by c .
- In the new prompt, enter tail -f file .
This method seems to be also a solution although there are quite several steps. I also like it! Thank you!
I use this script to achieve the effect you describe
!#/bin/bash while [ 1 ]; do ls -lt data | head -n 30; sleep 3; echo -en "$(tput cuu 30; tput ed)"; done
This runs a command in a loop, and deletes the last lines of the output from the screen before each iteration.
In your case it would look something like
!#/bin/bash while [ 1 ] ;# loop forever do head -n 2 job.sta ;# display first 2 lines tail -n 30 job.sta ;# display last 30 lines from file sleep 3 ;# wait a bit echo -en "$(tput cuu 32; tput ed)" ;# delete last 32 lines from screen done
Of course it is a bit ugly before your file reaches 30 lines
How to ‘Follow’ a File in Linux? Grep? Pipe? WGET Etc
The requirement is essentially to monitor changes on /HelloWorld.txt, so that any new lines that are added can be ‘picked up’ and piped to something like a WGET, for that single new line. I’m still in the early researching stages for how to chain these commands together (and ultimately turn into a Linux Daemon/Service/Systemctl ‘service’) From what I know already and what I’ve been reading to fill in the gaps, it kind of feels like this should be a relatively simply one line command in a bash/shell script which does something like ‘tail /HelloWorld.txt | wget example.com/HelloWorld’ I’ve yet to test any of this yet, so thought I’d post the question while I’m working away testing things in case I’m going in the wrong direction. UPDATE So looks like I am getting close to achieving a basic working example, but I’m seeing a lot of odd behaviour. Firstly, when running the command at the command line, I’m seeing the wrong data coming through. Secondly, when I turn this into a Linux Service, I not only see the wrong data coming through, but also multiple times and lots of spawned processes loitering that needed cleaning up. The command I’m running at the command line is;
tail -f -n 1 /myLog.txt | grep 'info_im_looking_for' --line-buffered | while read line; do xargs -d $'\n' -n 1 wget -q --delete-after --post-data "line=$" "https://www.example.com/HelloWorld"; done;
Seems I’m 95% of the way there, just struggling to get over the line. Feels as though if I can get this to work properly at the command line, I can figure out why the Linux Service isn’t quite working properly. What is odd is that when I just run the first bit of the command, this works fine and outputs to the console the info I would expect to see, it’s the bits afterwards that don’t seem to be quite working correctly;
tail -f -n 1 /myLog.txt | grep 'info_im_looking_for'
Note, my current thought process is that the parameter passing (which includes «s) is likely needing to be encoded, just in the process of taking a look at options for this. Feels like this is probably going to be easier to achieve via a .sh or .py script rather than one magic single line piped command to get this working.