Create a gist now

Instantly share code, notes, and snippets.

@amitsaha /
Last active Dec 27, 2017

What would you like to do?
Simple implementation of the tail command in Python
Basic tail command implementation
Usage: filename numlines
import sys
import linecache
if len(sys.argv) !=3:
print 'Usage: <file> <nlines>'
# filename and number of lines requested
fname, nlines = sys.argv[1:]
nlines = int(nlines)
# count the total number of lines
tot_lines = len(open(fname).readlines())
# use line cache module to read the lines
for i in range(tot_lines - nlines + 1, tot_lines+1):
print linecache.getline(sys.argv[1],i),
""" This is a more efficient version, since it does not read the entire
import sys
import os
bufsize = 8192
lines = int(sys.argv[1])
fname = sys.argv[2]
fsize = os.stat(fname).st_size
iter = 0
with open(sys.argv[2]) as f:
if bufsize > fsize:
bufsize = fsize-1
data = []
while True:
iter +=1*iter)
if len(data) >= lines or f.tell() == 0:

Excellent implementation! Simple and elegant. Well done man!

There's a couple of problems in the second implementation when you exceed the buffer size. f.tell() won't ever == 0 since it's after f.readlines(), and data isn't cleared before f.readlines() so you end up with duplicated data.

ksingh7 commented Jan 23, 2016

Another way of doing it


import sys

if len(sys.argv) !=3:
    print 'Usage: <file> <nlines>'

fname, nlines = sys.argv[1:]
num_lines = int(nlines)

with open(fname) as f:
    content =

count = len(content)
for i in range(count-num_lines,count):
  print content[i]

Kentzo commented Feb 23, 2016

And yet another way of doing this: tailhead and pytailer.

mikewen commented Feb 29, 2016

use deque:
from collections import deque
print deque(open(filename), nLines)

rodmur commented Apr 7, 2017

For what it's worth, I adapted some code from here, basically just using seek() and read() one at time to read backwards and count newlines, that way you don't need a buffer.


import os,sys

def tail_file(filename, nlines):
    with open(filename) as qfile:, os.SEEK_END)
        endf = position = qfile.tell()
        linecnt = 0
        while position >= 0:
            next_char =
            if next_char == "\n" and position != endf-1:
                linecnt += 1

            if linecnt == nlines:
            position -= 1

        if position < 0:


if __name__ == '__main__':
    filename = sys.argv[1]
    nlines = int(sys.argv[2])
    tail_file(filename, nlines)

I tried the second implementation with a ~1.7 GB file and works like a magic whereas the first one fails.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment