How to count the number of lines in a file using Bash?

I have a very large file (~9GB). I wish to remove the first 11 lines and the last 14 lines in place. How do I do that using a bash terminal command?

  • 'sed' is taking a lot of time.

  • Answer:

    As i know there is no kernel support for changing the start position of a file in place, you still have to make a full copy of the file content. To end a file earlier, simply use ftruncate(int fildes, off_t length). I am not aware of any cmd-tool that makes this simply for you :( If its something you will make regularly, it is only a few rows of c-code to write.

Jimmy Wennlund at Quora Visit the source

Was this solution helpful to you?

Other answers

Tricky, because to skip all but the last 14 lines requires reading 14 lines ahead, because you don't know in advance how many lines there are. Here is a one-liner using awk: awk 'BEGIN {NSTART = 11; NEND = 14} NR>NSTART {a[NEND + 1] = $0; for (i=1; i < NEND + 2; i++) a[i - 1] = a[i]; if(a[0]) print a[0]}' < input_file > output_file Note that there is no way in bash to modify the file in place; you have to make a copy. if you try to use the same value for the input and output file names in the code above, you will delete all the content from your input file. In principle this shouldn't be too slow since it is only operating on one line at a time, but I haven't tested it with any large files. Edit: On my machine, this produces output at about 11 MB/minute, so a 9 GB file would take about 15 hours. Of course, this code is a very inefficient implementation of a FIFO queue, since it shifts every value over by one every iteration. Here is a more efficient version using a ring buffer, which would take about 2 hours for a 9 GB file on my machine: awk 'BEGIN { NSTART = 11; head = NEND = 14; tail=0; } NR>NSTART { a[head]=$0; head=(head+1)%(NEND+1); if(a[tail]) print a[tail]; tail=(tail+1)%(NEND+1)}' < input_file > output_file Moral: awk is probably not the right tool for this job.

Tom Quetchenbach

Short answer: you don't ... there is no way to do that with just bash and common shell scripting tools. Better answer: it can be done using a programming language (to the degree that this goes beyond just "scripting" language features). For example using Python on a 64-bit system you could use the mmap module (included in the standard libraries) ... search for the offset to the eleventh newline, and to the 14th line from the end of the file, then use a simple range assignment mm[0:xx]=mm[zz:yy] ... to shift all the data over (where xx = yy - zz, and zz and yy are the offsets you found earlier). Then sync and close the memory mapping and your done. I'm currently editing this on my iPad and don't have easy access to write, test, and posted the exact code right now.  So this answer is just to give you the rough idea. For a 32-bit constrained version of Python it might still be possible ...  but would require a version of Python with the LFS (large file support) and  you'd have to perform a sequence of memory mappings in 2GB strides with offsets.  It's all quite tedious and far easier on almost all modern mainstream desktop and server hardware ... which has been 64-bit for about a decade now. Let me know of you try that approach and get stuck.  I'll write something up and test it.  (Mostly a matter of being studious about the offsets and fenceposts ... adding or subtracting one from this or that end of the range to be sure your getting exactly what you want.

Jim Dennis

It can be done with sed: sed -i -e '1,11d' -e :a -e '$d;N;2,25ba' -e 'P;D' file.txt ,25 here means 'last 14 lines' (11+14=25). In place(-i switch) and in one pass with the '11+14' trick.

Mauro Lacy

I agree with the other people... sort of. No, bash doesn't have the functions required. It depends what you mean by "remove". If you want to overwrite a bunch of characters at the beginning with spaces, then yes you can, but otherwise you'll need to copy the file to have it "start" at a later point. Shortening the file is possible with a program.. see truncate/ftruncate. http://man7.org/linux/man-pages/man2/ftruncate.2.html

Paul Mansfield

From http://stackoverflow.com/questions/4881930/bash-remove-the-last-line-from-a-file: dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc ) I think the above is the best solution, but try it and make sure it works in a test environment (as with all tips found online). An alternative (if you can be interactive) might also be to use Vi, but I am not sure and have not tested this approach. Start Vi in read-only mode (to ensure it will work in-place), and use ctrl+c on startup to stop it from trying to buffer the entire file in memory. Make your edits (d11d' to delete the first 11 lines, d11d' to delete the first 11 lines, :$-13' to jump to the 14th line from the bottom, `d14d' to remove the 14 lines from the current location). Now issue `:w!' to write while overriding the read-only setting; this should have the effect of overwriting the existing file Again, I'm not sure whether this would work!

Anonymous

Related Q & A:

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.