766

I have a very long file which I want to print, skipping the first 1,000,000 lines, for example.

I looked into the cat man page, but I did not see any option to do this. I am looking for a command to do this or a simple Bash program.

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Eduardo
  • 19,928
  • 23
  • 65
  • 73

13 Answers13

1242

Use tail. Some examples:

$ tail file.log
< Last 10 lines of file.log >

To SKIP the first N lines:

$ tail -n +<N+1> <filename>
< filename, excluding first N lines. >

For instance, to skip the first 10 lines:

$ tail -n +11 file.log
< file.log, starting at line 11, after skipping the first 10 lines. >

To see the last N lines, omit the "+":

$ tail -n <N> <filename>
< last N lines of file. >
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
SingleNegationElimination
  • 151,563
  • 33
  • 264
  • 304
  • 91
    Or "tail --lines=+ ..." for the readable-commands crowd :-) – paxdiablo Mar 03 '09 at 02:34
  • 48
    in centos 5.6 `tail -n +1` shows the whole file and `tail -n +2` skips first line. strange. The same for `tail -c +`. – NickSoft Sep 01 '11 at 10:23
  • Nick you may be running up against windows style line endings. – Joel Clark Nov 28 '11 at 18:06
  • 23
    @JoelClark No, @NickSoft is right. On Ubuntu, it's `tail -n +`, I just tested it. So `tail -n +1` won't skip anything, but start from the first line instead. – Andres F. Aug 22 '12 at 14:36
  • 34
    I can confirm that `tail -n +2` is required to skip the first line on Darwin/Mac OS X as well. – morgant Mar 24 '14 at 16:40
  • 4
    this must be outdated, but, tail -n+2 OR tail -n +2 works, as with all short commands using getopt, you can run the parameter right next to it's switch, providing that the switch is the last in the group, obviously a command like tail -nv+2 would not work, it would have to be tail -vn+2. if you dont believe me try it yourself. – osirisgothra May 03 '14 at 11:35
  • On Solaris, you need to use: `/usr/xpg4/bin/tail` (found this in the man page). – Andrew Sep 13 '17 at 21:09
  • 1
    Think I discovered this by accident but both head and tail allow you to omit the `-n` as if it's implied. You can simply ` | tail +2` – Lon Kaut Aug 01 '19 at 18:33
176

Easiest way I found to remove the first ten lines of a file:

$ sed 1,10d file.txt

In the general case where X is the number of initial lines to delete, credit to commenters and editors for this:

$ sed 1,Xd file.txt
David Parks
  • 30,789
  • 47
  • 185
  • 328
  • 15
    In the more general case, you'd have to use `sed 1,Xd` where X is the number of initial lines to delete, with X greater than 1. – Asclepius Dec 24 '13 at 00:10
  • 2
    This makes more sense if you don't know how long the file is and don't want to tell `tail` to print the last 100000000 lines. – springloaded Aug 29 '18 at 15:06
  • 1
    @springloaded if you need to know the number of lines in the file, ‘wc -l’ will easily give it to you – Mike Pennington Jun 10 '20 at 11:21
118

If you have GNU tail available on your system, you can do the following:

tail -n +1000001 huge-file.log

It's the + character that does what you want. To quote from the man page:

If the first character of K (the number of bytes or lines) is a `+', print beginning with the Kth item from the start of each file.

Thus, as noted in the comment, putting +1000001 starts printing with the first item after the first 1,000,000 lines.

MERose
  • 4,048
  • 7
  • 53
  • 79
Eddie
  • 53,828
  • 22
  • 125
  • 145
  • Works for BSD tail too (OS X) – Lloeki Nov 17 '16 at 13:59
  • @Lloeki Awesome! BSD head doesn't support negative numbers like GNU does, so I assumed tail didn't accept positives (with +) since that's sort of the opposite. Anyway, thanks. – Joel Mellon May 26 '21 at 19:03
  • 1
    Also, to clarify this answer: `tail -n +2 huge-file.log` would skip first line, and pick up on line 2. So to skip the first line, use +2. @saipraneeth's answer does a good job of exaplaining this. – Joel Mellon May 26 '21 at 19:07
63

If you want to skip first two line:

tail -n +3 <filename>

If you want to skip first x line:

tail -n +$((x+1)) <filename>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
saipraneeth
  • 747
  • 5
  • 3
  • 5
    This is somewhat misleading because someone may interpret `(x+1)` literally. For example, for x=2, they may type either `(2+1)` or even `(3)`, neither of which would work. A better way to write it might be: To skip the first X lines, with Y=X+1, use `tail -n +Y ` – Asclepius Dec 24 '13 at 17:11
41

A less verbose version with AWK:

awk 'NR > 1e6' myfile.txt

But I would recommend using integer numbers.

newtover
  • 31,286
  • 11
  • 84
  • 89
  • 9
    useful if you need to skip some lines in the middle of the file, e.g., `awk '!(5 < NR && NR < 10)'` – arekolek Jul 28 '16 at 12:24
  • This version works in the Cygwin tools that come with Git for Windows, whereas `tail` and `sed` do not. For example `git -c color.status=always status -sb | awk 'NR > 1'` gives a nice minimal status report without any branch information, which is useful when your shell already shows branch info in your prompt. I assign that command to alias `gs` which is really easy to type. – Drew Noakes Oct 08 '21 at 05:59
25

Use the sed delete command with a range address. For example:

sed 1,100d file.txt # Print file.txt omitting lines 1-100.

Alternatively, if you want to only print a known range, use the print command with the -n flag:

sed -n 201,300p file.txt # Print lines 201-300 from file.txt

This solution should work reliably on all Unix systems, regardless of the presence of GNU utilities.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
maerics
  • 151,642
  • 46
  • 269
  • 291
  • 1
    Most readily usable answer for both cli and scripting. – cerd Dec 01 '17 at 01:37
  • You can use `$` as "address" of eof: `sed -n '201,$p' file.txt`, i.e. *print file from line 201 to the end*. – TNT May 25 '23 at 17:20
24

Use:

sed -n '1d;p'

This command will delete the first line and print the rest.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
17

If you want to see the first 10 lines you can use sed as below:

sed -n '1,10 p' myFile.txt

Or if you want to see lines from 20 to 30 you can use:

sed -n '20,30 p' myFile.txt
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kadir YILDIZ
  • 171
  • 1
  • 2
14

Just to propose a sed alternative. :) To skip first one million lines, try |sed '1,1000000d'.

Example:

$ perl -wle 'print for (1..1_000_005)'|sed '1,1000000d'
1000001
1000002
1000003
1000004
1000005
tuomassalo
  • 8,717
  • 6
  • 48
  • 50
  • 2
    @Marlon, sorry but that's wrong. That only works for 1d. If, for example, you use it on 2d, you'll delete only line 2. It doesn't delete the range of lines. – Asclepius Dec 24 '13 at 17:19
  • @A-B-B sorry, meant to say that this was the easiest solution by far which is why I +1 it not trying to correct the author. – Marlon Jan 14 '14 at 19:40
13

You can do this using the head and tail commands:

head -n <num> | tail -n <lines to print>

where num is 1e6 + the number of lines you want to print.

Dana the Sane
  • 14,762
  • 8
  • 58
  • 80
  • 3
    Not the most efficient answer since you'd need to do a "wc -l" on the file to get a line count, followed by an addition to add the million :-). You can do it with just "tail". – paxdiablo Mar 03 '09 at 02:43
  • I'm not sure, my understanding was that 1e6 would be known at the time of calling. Counting backwards isn't the fastest though. – Dana the Sane Mar 03 '09 at 03:11
11

This shell script works fine for me:

#!/bin/bash
awk -v initial_line=$1 -v end_line=$2 '{
    if (NR >= initial_line && NR <= end_line) 
    print $0
}' $3

Used with this sample file (file.txt):

one
two
three
four
five
six

The command (it will extract from second to fourth line in the file):

edu@debian5:~$./script.sh 2 4 file.txt

Output of this command:

two
three
four

Of course, you can improve it, for example by testing that all argument values are the expected :-)

sourcerebels
  • 5,140
  • 1
  • 32
  • 52
5
cat < File > | awk '{if(NR > 6) print $0}'
C. A. McCann
  • 76,893
  • 19
  • 209
  • 302
aamadeo
  • 347
  • 4
  • 10
-2

I needed to do the same and found this thread.

I tried "tail -n +, but it just printed everything.

The more +lines worked nicely on the prompt, but it turned out it behaved totally different when run in headless mode (cronjob).

I finally wrote this myself:

skip=5
FILE="/tmp/filetoprint"
tail -n$((`cat "${FILE}" | wc -l` - skip)) "${FILE}"
  • 2
    Correct link of [Useless Use of Cat Award](http://porkmail.org/era/unix/award.html). The previous is replaced by advert. – kub1x Jul 26 '17 at 13:01
  • 1
    @kub1x I don't think "cat" here is useless, as "cat | wc -l" produces different output than simple "wc -l". The former is suitable for arithmetic operations, the latter is not. – Jack Jan 15 '18 at 10:14
  • @Jack I wasn't judging the use of `cat`, but only fixing a link in a comment, that led to a dead page. The original comment must have been deleted. Anyways, thanks for pointing that out. – kub1x Jan 15 '18 at 11:55
  • 1
    @kub1x You know? After reading the link now I think that the use of "cat" here is wrong :) It should has been something like "wc -l < ${FILE}", saving some overhead time/memory (new process creation, pipelining I/O,.. ). Thanks, I've learned something new – Jack Jan 16 '18 at 09:43