Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to print the odd-numbered and even-numbered lines from files.

I found this shell script which makes use of echo.

# Write a shell script that, given a file name as the argument will write
# the even numbered line to a file with name evenfile and odd numbered lines
# in a text file called oddfile.
# -------------------------------------------------------------------------
# Copyright (c) 2001 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------


eout="evenfile.$$" # even file name
oout="oddfile.$$" # odd file name

if [ $# -eq 0 ]
    echo "$(basename $0) file"
    exit 1

if [ ! -f $file ]
    echo "$file not a file"
    exit 2

while read line
    # find out odd or even line number
    isEvenNo=$( expr $counter % 2 )

    if [ $isEvenNo -ne 0 ]
        # even match
        echo $line >> $eout
        # odd match
        echo $line >> $oout
    # increase counter by 1
    (( counter ++ ))
done < $file
echo "Even file - $eout"
echo "Odd file - $oout"

But isn't there a way to do it in one line?

Yes, use awk, I read.

Even-numbered lines:

awk 'NR % 2' filename

odd-numbered lines:

awk 'NR % 2 == 1' filename

But it doesn't work for me. Both produce the same output, according to diff. When compared to the original file, they are both indeed half as long, and they both contain the odd-numbered lines. Am I doing something wrong?

share|improve this question
The first one should be NR % 2 == 0, otherwise it is equivalent to the second one. – enzotib Dec 13 '11 at 11:49
There seem to be several documents online (including this one) that show up at the top of a search that state that NR % 2 gives you the even numbered lines, which is not correct, it gives you the odd because 1 % 2 = 1 = true, 2 % 2 = 0 = false. – deltaray Jan 24 '12 at 16:29
up vote 8 down vote accepted

As you asked “in one line”:

awk '{print>sprintf("%sfile.%d",NR%2?"odd":"even",PROCINFO["pid"])}' filename

Note that most of the code is due to your fancy output filename choice. Otherwise the following code would be enough to put odd lines in “line-1” and even lines in “line-0”:

awk '{print>"line-"NR%2}' filename
share|improve this answer

That's easy:

 sed -n 2~2p filename

will print even-numbered lines from filename

sed -n 1~2p filename

will print odd-numbered lines.

share|improve this answer
+1, for not using AWK extraneously. Not POSIX sed, but it's still solid method. – TechZilla Nov 1 '12 at 14:33
@TechZilla I don't understand "using AWK extraneously" - awk is POSIX as well. – jw013 Nov 1 '12 at 15:31
@jw013: Nothing is wrong with awk, personally I use it very often. I never said anything was 'Not POSIX' about awk, I was referring to the answer's sed options. Specifically the ~ operator, it's a GNU extension, which is still acceptable for many people. Regarding 'using AWK extraneously, I personally believe using awk` for this simple task is overkill. So the +1 was for for completing the task with sed, a lighter utility than awk. – TechZilla Nov 1 '12 at 15:55

I prefer to be POSIX compatible, whenever possible, so I thought I'd post this alternative method. I often use these to mangle text, before xargs pipelines.

Print Even Numbered Lines,

sed -n 'n;p'

Print Odd Numbered Lines,

sed -n 'p;n'

Although I often use awk, it's overkill for this type of task.

share|improve this answer
+1 this is a brilliant one! The simplicity... – peterph Feb 13 '14 at 14:20

You can do it with a single sed invocation, no need to read the file twice:

sed '$!n
w even
d' infile > odd

or, if you prefer in one line:

sed -e '$!n' -e 'w even' -e d infile > odd

Note that these won't give the expected result if a file contains only one line (the line will be written to even instead of odd as the first n isn't executed). To avoid that, add a condition:

sed -e '$!n' -e '1!{w even' -e 'd}' infile > odd
share|improve this answer

Try this:

awk '{if(NR%2){print $0 > "odd.file"}else{print $0 > "even.file"}}' filename
share|improve this answer
Are you sure about outputting the record numbers? – manatwork Dec 13 '11 at 12:17
sorry about that, I modified it to output the whole lines. – renma Dec 13 '11 at 12:29

For even numbers the code should be

awk 'NR%2==0' filename

& for odd numbers

awk 'NR%2==1' filename
share|improve this answer

I'd go with perl because I like perl:

perl -pe 'BEGIN{open($e,">even_lines");open($o,">odd_lines")} $. % 2 ?select $o:select $e;'

Uses the fact that -p implicitly prints, to replicated how sed works - and we use select to choose which file handle to which it writes.

share|improve this answer

protected by Community Oct 26 '15 at 3:48

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.