- How can I read first n and last n lines from a file?
- 10 Answers 10
- Explanation
- UNIX for Dummies Questions & Answers
- Easiest way to cat out first 100 lines of a file into a different file?
- 10 More Discussions You Might Find Interesting
- 1. Shell Programming and Scripting
- Find all lines in file such that each word on that line appears in at least n lines of the file
- 2. Shell Programming and Scripting
- Ssh cat file output into a file on local computer
- 3. UNIX for Dummies Questions & Answers
- Cat command drops lines in output file
- 4. Shell Programming and Scripting
- Cat Command on File not printing «Blank» Lines?
- 5. Shell Programming and Scripting
- split a line of a file and cat a file with another
- View files using – cat, more, tail, head and wc commands
- cat Command
- more Command
- head Command
- tail Command
- wc Command
How can I read first n and last n lines from a file?
How can I read the first n lines and the last n lines of a file? For n=2 , I read online that (head -n2 && tail -n2) would work, but it doesn’t.
$ cat x 1 2 3 4 5 $ cat x | (head -n2 && tail -n2) 1 2
Also, the link you sent is not helpful because I do not know the range really. I am looking for a simple solution for this
Interestingly, cat x | (head -n2 && tail -n2) doesn’t work but (head -n2 && tail -n2) < x does. I'll have to meditate a bit on why that is.
What would the expected output be if the input file was 3 lines long? Would it be 1 2 3 or 1 2 2 3 or something else? What if it was only 2 lines long — would the output be 1 2 1 2 or 1 1 2 2 or 1 2 or something else?
I don’t think the head && tail trick is reliable. head from GNU coreutils behaves differently for pipes and regular files (source: the source), reading blockwise in one case but not the other. Depending on implementation details like that seems like a bad idea — it’s not guaranteed that head will leave everything it doesn’t print for tail to work with.
10 Answers 10
head -n2 file && tail -n2 file
This isn’t guaranteed to work even if your file is longer than 4 lines, if a single head buffer is so long enough that there aren’t enough lines left in the file for tail to work.
Chances are you’re going to want something like:
or if you need to specify a number and taking into account @Wintermute’s astute observation that you don’t need to buffer the whole file, something like this is what you really want:
I think the math is correct on that — hopefully you get the idea to use a rotating buffer indexed by the NR modded by the size of the buffer and adjusted to use indices in the range 1-n instead of 0-(n-1).
To help with comprehension of the modulus operator used in the indexing above, here is an example with intermediate print statements to show the logic as it executes:
$ cat tst.awk BEGIN < print "Populating array by index ((NR-1)%n)+1:" > < buf[((NR-1)%n)+1] = $0 printf "NR=%d, n=%d: ((NR-1 = %d) %%n = %d) +1 = %d ->buf[%d] = %s\n", NR, n, NR-1, (NR-1)%n, ((NR-1)%n)+1, ((NR-1)%n)+1, buf[((NR-1)%n)+1] > END < print "\nAccessing array by index ((NR+i-1)%n)+1:" for (i=1;i<=n;i++) < printf "NR=%d, i=%d, n=%d: (((NR+i = %d) - 1 = %d) %%n = %d) +1 = %d ->buf[%d] = %s\n", NR, i, n, NR+i, NR+i-1, (NR+i-1)%n, ((NR+i-1)%n)+1, ((NR+i-1)%n)+1, buf[((NR+i-1)%n)+1] > > $ $ awk -v n=3 -f tst.awk file Populating array by index ((NR-1)%n)+1: NR=1, n=3: ((NR-1 = 0) %n = 0) +1 = 1 -> buf[1] = 1 NR=2, n=3: ((NR-1 = 1) %n = 1) +1 = 2 -> buf[2] = 2 NR=3, n=3: ((NR-1 = 2) %n = 2) +1 = 3 -> buf[3] = 3 NR=4, n=3: ((NR-1 = 3) %n = 0) +1 = 1 -> buf[1] = 4 NR=5, n=3: ((NR-1 = 4) %n = 1) +1 = 2 -> buf[2] = 5 NR=6, n=3: ((NR-1 = 5) %n = 2) +1 = 3 -> buf[3] = 6 NR=7, n=3: ((NR-1 = 6) %n = 0) +1 = 1 -> buf[1] = 7 NR=8, n=3: ((NR-1 = 7) %n = 1) +1 = 2 -> buf[2] = 8 Accessing array by index ((NR+i-1)%n)+1: NR=8, i=1, n=3: (((NR+i = 9) - 1 = 8) %n = 2) +1 = 3 -> buf[3] = 6 NR=8, i=2, n=3: (((NR+i = 10) - 1 = 9) %n = 0) +1 = 1 -> buf[1] = 7 NR=8, i=3, n=3: (((NR+i = 11) - 1 = 10) %n = 1) +1 = 2 -> buf[2] = 8
+1 since this works in a pipe. You might add a more elaborated version which takes files (streams) into account having less then 4 (head+tail) lines..
@EdMorton But it would still need to buffer the whole stream in memory.. (However I don’t see a way without buffering if it should work in a pipe, except saving the stream into a temporary file)
I understand but the bug was just that I was setting ORS=’\n’ when I should have been setting OFS=’\n’ . Now that that’s fixed there’s no need to explicitly hard-code «\n» s between fields.
This might work for you (GNU sed):
This keeps a window of 2 (replace the 2’s for n) lines and then prints the first 2 lines and at end of file prints the window i.e. the last 2 lines.
Here’s a GNU sed one-liner that prints the first 10 and last 10 lines:
If you want to print a ‘—‘ separator between them:
If you’re on a Mac and don’t have GNU sed, you can’t condense as much:
Explanation
gsed -ne’ invoke sed without automatic printing pattern space
-e’1,9′ print the first 9 lines
-e’10’ print line 10 with an appended ‘—‘ separator
-e’:a;$p;N;21,$D;ba’ print the last 10 lines
If you are using a shell that supports process substitution, another way to accomplish this is to write to multiple processes, one for head and one for tail . Suppose for this example your input comes from a pipe feeding you content of unknown length. You want to use just the first 5 lines and the last 10 lines and pass them on to another pipe:
cat | < tee >(head -5) >(tail -10) 1>/dev/null> | cat
The use of <> collects the output from inside the group (there will be two different programs writing to stdout inside the process shells). The 1>/dev/null is to get rid of the extra copy tee will try to write to it’s own stdout.
That demonstrates the concept and all the moving parts, but it can be simplified a little in practice by using the STDOUT stream of tee instead of discarding it. Note the command grouping is still necessary here to pass the output on through the next pipe!
cat | < tee >(head -5) | tail -15 > | cat
Obviously replace cat in the pipeline with whatever you are actually doing. If your input can handle the same content to writing to multiple files you could eliminate the use of tee entirely as well as monkeying with STDOUT. Say you have a command that accepts multiple -o output file name flags:
UNIX for Dummies Questions & Answers
Easiest way to cat out first 100 lines of a file into a different file?
Top Forums UNIX for Dummies Questions & Answers Easiest way to cat out first 100 lines of a file into a different file?
n/a, 0
Not sure how to do this exactly.. just want to take the first 100 lines of a file and cat it out into a second file. I know I can do a more on a file and > it into a different file, but how can I make it so only the first 100 lines get moved over?
740, 2
# head -100 oldfile > newfile
10 More Discussions You Might Find Interesting
1. Shell Programming and Scripting
Find all lines in file such that each word on that line appears in at least n lines of the file
I have a file where every line includes four expressions with a caret in the middle (plus some other «words» or fields, always separated by spaces). I would like to extract from this file, all those lines such that each of the four expressions containing a caret appears in at least four different. (9 Replies)
Discussion started by: uncleMonty
2. Shell Programming and Scripting
Ssh cat file output into a file on local computer
Hello, I’m on a remote computer by SSH. How can I get the output of «cat file» into a file on the local computer? I cannot use scp, because it’s blocked. something like: ssh root@remote_maschine «cat /file» > /locale_machine/file :rolleyes: (2 Replies)
Discussion started by: borsti007
3. UNIX for Dummies Questions & Answers
Cat command drops lines in output file
I use the cat command to concatenate text files, but one of the rows I was expecting doesn’t display in the output file. Is there a verbose mode\logging mechanism for the cat command to help me investigate where the lines I was expecting are going?? cat 7760-001_1_*_06_*.txt | grep -v. (1 Reply)
Discussion started by: Xin Xin
4. Shell Programming and Scripting
Cat Command on File not printing «Blank» Lines?
Hello All, I have a bash script and in it at some point I call an Expect Script that does some stuff and saves its output in a «.txt» file. Example «/path/to/my/file/Expect_Output.txt» file: notice the 2nd line is empty in the file. Data for Host-1 (192.168.1.110) Checking the. (2 Replies)
Discussion started by: mrm5102
5. Shell Programming and Scripting
split a line of a file and cat a file with another
Hi, I have two files one.txt laptop boy apple two.txt unix linux OS openS I want to split one.txt into one line each and concatenate it with the two.txt output files onea.txt laptop (4 Replies)
View files using – cat, more, tail, head and wc commands
There are several commands that display information about a file in the read-only format. The file-viewing commands include the following:
cat Command
The cat command displays the content of one or more text files on the screen without pausing.
# cat data.txt northwest NW Joel Craig 10 western WE Sharon Kelly 40 southwest SW Chris Foster 33 central CT Sheri Watson 44
Do not use the cat command to read binary files. Using the cat command to read binary files can cause a terminal window to freeze. If your terminal window freezes, close the terminal window, and open a new terminal window.
Note: Before you attempt to open a file with the cat command, it is recommended that you first run the file command to determine the file type.
more Command
The more command displays the content of a text file one screen at a time.
message appears at the bottom of each screen, where n% is the percentage of the file that has been displayed. When the entire file has been displayed, the shell prompt appears.
When the –More–(n%)prompt appears at the bottom of the screen, you can use the keys described in the table to scroll through the file.
Keyboard Command | Action |
---|---|
Space bar | Moves forward one screen |
Return | Scrolls one line at a time |
b | Moves back one screen |
h | Displays a help menu of features |
/string | Searches forward for pattern |
n | Finds the next occurrence of pattern |
q | Quits and returns to the shell prompt |
head Command
The head command displays the first 10 lines of a file.
You can change the number of lines displayed by using the -n option. For example, to display the first five lines of the /var/log/messages file, enter the head command with the -n option set to 5.
tail Command
The tail command displays the last 10 lines of a file.
You can change the number of lines displayed by using the -n or +n options.
– The -n option displays n lines from the end of the file.
– The +n option displays the file from line n to the end of the file.
For example, to display the last four lines of the /var/log/messages file, enter the tail command with the -n option set to 4.
For example, to display line 10 through the end of the data.txt file, enter the tail command with the +n option set to 10.
wc Command
The wc command displays the number of lines, words, and characters contained in a file.
You can use the following options with the wc command.
Symbol | Description |
---|---|
-l | Line count |
-w | Word count |
-c | Byte count |
-m | Character count |
When you use the wc command without options, the output displays the number of lines, words, and characters contained in the file. For example, to display the number of lines, words, and characters in the dante file, use the wc command.
$ wc data.txt 32 223 1319 data.txt
For example, to display the number of lines in the dante file, enter the wc command with the -l option.